From 7dd9a998514f56bc567137eee4c0161409cab6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Fri, 29 Sep 2023 19:53:04 +0300 Subject: [PATCH] Paymaster tests --- contracts/paymaster/Cargo.toml | 3 + contracts/paymaster/src/forward_call.rs | 1 - .../tests/paymaster_blackbox_test.rs | 202 +++++++++++++++--- .../paymaster/tests/test-contracts/adder.wasm | Bin 0 -> 685 bytes 4 files changed, 178 insertions(+), 28 deletions(-) create mode 100755 contracts/paymaster/tests/test-contracts/adder.wasm diff --git a/contracts/paymaster/Cargo.toml b/contracts/paymaster/Cargo.toml index dcf17029..1f21e569 100644 --- a/contracts/paymaster/Cargo.toml +++ b/contracts/paymaster/Cargo.toml @@ -16,3 +16,6 @@ version = "0.43.4" [dev-dependencies.multiversx-sc-scenario] version = "0.43.4" + +[dev-dependencies.adder] +path = "../adder" diff --git a/contracts/paymaster/src/forward_call.rs b/contracts/paymaster/src/forward_call.rs index 8a721324..d230012a 100644 --- a/contracts/paymaster/src/forward_call.rs +++ b/contracts/paymaster/src/forward_call.rs @@ -37,7 +37,6 @@ pub trait ForwardCall { fn transfer_callback( &self, original_caller: ManagedAddress, - // initial_payments: ManagedVec>, #[call_result] result: ManagedAsyncCallResult>, ) -> MultiValueEncoded { let initial_payments = self.call_value().all_esdt_transfers(); diff --git a/contracts/paymaster/tests/paymaster_blackbox_test.rs b/contracts/paymaster/tests/paymaster_blackbox_test.rs index 53a12b98..8d3bf45d 100644 --- a/contracts/paymaster/tests/paymaster_blackbox_test.rs +++ b/contracts/paymaster/tests/paymaster_blackbox_test.rs @@ -1,84 +1,232 @@ -use multiversx_sc::types::Address; -use multiversx_sc_scenario::{api::StaticApi, *, scenario_model::{ScDeployStep, AddressValue, Account, SetStateStep}}; -use paymaster::ProxyTrait; +use multiversx_sc::{ + codec::{multi_types::MultiValueVec, top_encode_to_vec_u8_or_panic}, + storage::mappers::SingleValue, + types::{Address, BigUint}, +}; +use multiversx_sc_scenario::{ + api::StaticApi, + scenario_model::{ + Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, ScQueryStep, + SetStateStep, TxExpect, + }, + *, +}; + +use adder::ProxyTrait as _; +use paymaster::ProxyTrait as _; const PAYMASTER_ADDRESS_EXPR: &str = "sc:paymaster"; -const RELAYER_ADDRESS_EXPR: &str = "sc:relayer"; -const CALLEE_SC_ADDRESS_EXPR: &str = "sc:callee_sc"; +const RELAYER_ADDRESS_EXPR: &str = "address:relayer"; +const CALLEE_SC_ADDER_ADDRESS_EXPR: &str = "sc:adder"; const PAYMASTER_PATH_EXPR: &str = "file:output/paymaster.wasm"; +const ADDER_PATH_EXPR: &str = "file:tests/test-contracts/adder.wasm"; const CALLER_ADDRESS_EXPR: &str = "address:caller"; const CALLEE_USER_ADDRESS_EXPR: &str = "address:callee_user"; const OWNER_ADDRESS_EXPR: &str = "address:owner"; const BALANCE: &str = "100,000,000"; +const PAYMASTER_TOKEN_ID_EXPR: &str = "str:PAYMSTR-123456"; +const FEE_TOKEN_ID_EXPR: &str = "str:FEE-123456"; +const FEE_AMOUNT: &str = "20,000"; +const INITIAL_ADD_VALUE: u64 = 5; +const ADDITIONAL_ADD_VALUE: u64 = 5; + + type PaymasterContract = ContractInfo>; +type AdderContract = ContractInfo>; fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.set_current_dir_from_workspace("contracts/examples/empty"); + blockchain.set_current_dir_from_workspace("contracts/paymaster"); + + blockchain.register_contract(PAYMASTER_PATH_EXPR, paymaster::ContractBuilder); + blockchain.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - blockchain.register_contract("file:output/paymaster.wasm", paymaster::ContractBuilder); blockchain } struct PaymasterTestState { world: ScenarioWorld, - caller_address: Address, callee_user_address: Address, paymaster_contract: PaymasterContract, relayer_address: Address, - callee_sc_address: Address, + callee_sc_adder_contract: AdderContract, } impl PaymasterTestState { fn new() -> Self { let mut world = world(); - world.set_state_step( + world.start_trace().set_state_step( SetStateStep::new() .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) .put_account( CALLER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .balance(BALANCE) + .esdt_balance(PAYMASTER_TOKEN_ID_EXPR, BALANCE) + .esdt_balance(FEE_TOKEN_ID_EXPR, BALANCE), + ) + .put_account( + CALLEE_USER_ADDRESS_EXPR, Account::new().nonce(1).balance(BALANCE), ) - .put_account(CALLEE_USER_ADDRESS_EXPR, Account::new().nonce(1).balance(BALANCE)) - .new_address(OWNER_ADDRESS_EXPR, 1, PAYMASTER_ADDRESS_EXPR) - .new_address(OWNER_ADDRESS_EXPR, 1, RELAYER_ADDRESS_EXPR) - .new_address(OWNER_ADDRESS_EXPR, 1, CALLEE_SC_ADDRESS_EXPR), + .put_account(RELAYER_ADDRESS_EXPR, Account::new().nonce(1).balance(0u32)), ); - let paymaster_contract = PaymasterContract::new(PAYMASTER_ADDRESS_EXPR); - - let caller_address = AddressValue::from(CALLER_ADDRESS_EXPR).to_address(); let callee_user_address = AddressValue::from(CALLEE_USER_ADDRESS_EXPR).to_address(); let relayer_address = AddressValue::from(RELAYER_ADDRESS_EXPR).to_address(); - let callee_sc_address = AddressValue::from(CALLEE_SC_ADDRESS_EXPR).to_address(); + let paymaster_contract = PaymasterContract::new(PAYMASTER_ADDRESS_EXPR); + let callee_sc_adder_contract = AdderContract::new(CALLEE_SC_ADDER_ADDRESS_EXPR); + // let callee_sc_adder_address = AddressValue::from(CALLEE_SC_ADDER_ADDRESS_EXPR).to_address(); Self { world, - caller_address, callee_user_address, paymaster_contract, relayer_address, - callee_sc_address, + callee_sc_adder_contract, } } fn deploy_paymaster_contract(&mut self) -> &mut Self { let paymaster_code = self.world.code_expression(PAYMASTER_PATH_EXPR); - self.world.sc_deploy( - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(paymaster_code) - .call(self.paymaster_contract.init()), - ); + self.world + .set_state_step(SetStateStep::new().new_address( + OWNER_ADDRESS_EXPR, + 1, + PAYMASTER_ADDRESS_EXPR, + )) + .sc_deploy( + ScDeployStep::new() + .from(OWNER_ADDRESS_EXPR) + .code(paymaster_code) + .call(self.paymaster_contract.init()), + ); + + self + } + + fn deploy_adder_contract(&mut self) -> &mut Self { + let adder_code = self.world.code_expression(ADDER_PATH_EXPR); + + self.world + .set_state_step(SetStateStep::new().new_address( + OWNER_ADDRESS_EXPR, + 2, + CALLEE_SC_ADDER_ADDRESS_EXPR, + )) + .sc_deploy( + ScDeployStep::new() + .from(OWNER_ADDRESS_EXPR) + .code(adder_code) + .call(self.callee_sc_adder_contract.init(INITIAL_ADD_VALUE)), + ); + + self + } + + fn check_esdt_balance( + &mut self, + address_expr: &str, + token_id_expr: &str, + balance_expr: &str, + ) -> &mut Self { + self.world + .check_state_step(CheckStateStep::new().put_account( + address_expr, + CheckAccount::new().esdt_balance(token_id_expr, balance_expr), + )); + self } } #[test] -fn test_deploy_paymaster() { +fn test_deploy_paymasters() { let mut state = PaymasterTestState::new(); state.deploy_paymaster_contract(); + state.deploy_adder_contract(); +} + +#[test] +fn test_forward_call_no_fee_payment() { + let mut state = PaymasterTestState::new(); + state.deploy_paymaster_contract(); + + state.world.sc_call( + ScCallStep::new() + .from(CALLER_ADDRESS_EXPR) + .call(state.paymaster_contract.forward_execution( + state.relayer_address.clone(), + state.callee_user_address.clone(), + managed_buffer!(b"add"), + MultiValueVec::>::new(), + )) + .expect(TxExpect::user_error("str:There is no fee for payment!")), + ); +} + +#[test] +fn test_forward_call_user() { + let mut state = PaymasterTestState::new(); + state.deploy_paymaster_contract(); + + state + .world + .sc_call( + ScCallStep::new() + .from(CALLER_ADDRESS_EXPR) + .call(state.paymaster_contract.forward_execution( + state.relayer_address.clone(), + state.callee_user_address.clone(), + managed_buffer!(b"add"), + MultiValueVec::>::new(), + )) + .esdt_transfer(FEE_TOKEN_ID_EXPR, 0, FEE_AMOUNT) + .expect(TxExpect::ok()), + ) + .check_state_step(CheckStateStep::new().put_account( + RELAYER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(FEE_TOKEN_ID_EXPR, FEE_AMOUNT), + )); +} + +#[test] +fn test_forward_call_sc_adder() { + let mut state = PaymasterTestState::new(); + state.deploy_paymaster_contract(); + state.deploy_adder_contract(); + + state.check_esdt_balance(CALLER_ADDRESS_EXPR, FEE_TOKEN_ID_EXPR, BALANCE); + state.check_esdt_balance(CALLER_ADDRESS_EXPR, PAYMASTER_TOKEN_ID_EXPR, BALANCE); + + state.world.sc_call( + ScCallStep::new() + .from(CALLER_ADDRESS_EXPR) + .esdt_transfer(FEE_TOKEN_ID_EXPR, 0, FEE_AMOUNT) + .esdt_transfer(PAYMASTER_TOKEN_ID_EXPR, 0, FEE_AMOUNT) + .call(state.paymaster_contract.forward_execution( + state.relayer_address.clone(), + state.callee_sc_adder_contract.to_address(), + managed_buffer!(b"add"), + MultiValueVec::from([top_encode_to_vec_u8_or_panic(&ADDITIONAL_ADD_VALUE)]), + )) + .expect(TxExpect::ok()), + ); + + let expected_adder_sum = INITIAL_ADD_VALUE + ADDITIONAL_ADD_VALUE; + state.world.sc_query( + ScQueryStep::new() + .call(state.callee_sc_adder_contract.sum()) + .expect_value(SingleValue::from(BigUint::from(expected_adder_sum))), + ); + state.check_esdt_balance(RELAYER_ADDRESS_EXPR, FEE_TOKEN_ID_EXPR, FEE_AMOUNT); + state.check_esdt_balance( + CALLEE_SC_ADDER_ADDRESS_EXPR, + PAYMASTER_TOKEN_ID_EXPR, + FEE_AMOUNT, + ); } diff --git a/contracts/paymaster/tests/test-contracts/adder.wasm b/contracts/paymaster/tests/test-contracts/adder.wasm new file mode 100755 index 0000000000000000000000000000000000000000..6e7ea0236e3b763a917d119dd2725703e4cb316f GIT binary patch literal 685 zcmZuvO^?$s5S_8JX*OmPv#mf~aR@!Zi5urlC5n*H3Tfe-xQ&}uZDQmkpq|p7uver# z@N@WA#ZJt8HG&EY^8b$g&1%`7oFDT~nOF3ecj=O2z(z)=Kxf>tf!l*HYitN{d{6 zRw4spr7s8KtD1L}&SiRbI@&kNBkTF0mK9vsYQbtFSGzm)MI5>r zz=D&0#>KYWR-32#j-@VpD$X)+Df1DX5w)8%ZV1#3Nel7sqsNA8v>3UCER;SFaEx6I z&t0>i`=)?vDvZh4TZ#RCE>=63_(_t9S|qZ}D6k~iNbx;cib_)S|DYcrwlVN$GvE*b zo7(X4=-KZLff#o)cuy=d0ge$YoZFDaMK7Sky=M$_>rp0tjCVUoX6AY^cSE_s22bL literal 0 HcmV?d00001