Skip to content

Commit

Permalink
Paymaster tests
Browse files Browse the repository at this point in the history
  • Loading branch information
CostinCarabas committed Sep 29, 2023
1 parent ef0289e commit 7dd9a99
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 28 deletions.
3 changes: 3 additions & 0 deletions contracts/paymaster/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ version = "0.43.4"

[dev-dependencies.multiversx-sc-scenario]
version = "0.43.4"

[dev-dependencies.adder]
path = "../adder"
1 change: 0 additions & 1 deletion contracts/paymaster/src/forward_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ pub trait ForwardCall {
fn transfer_callback(
&self,
original_caller: ManagedAddress,
// initial_payments: ManagedVec<EsdtTokenPayment<Self::Api>>,
#[call_result] result: ManagedAsyncCallResult<MultiValueEncoded<ManagedBuffer>>,
) -> MultiValueEncoded<ManagedBuffer> {
let initial_payments = self.call_value().all_esdt_transfers();
Expand Down
202 changes: 175 additions & 27 deletions contracts/paymaster/tests/paymaster_blackbox_test.rs
Original file line number Diff line number Diff line change
@@ -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<paymaster::Proxy<StaticApi>>;
type AdderContract = ContractInfo<adder::Proxy<StaticApi>>;

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,

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / Contracts / Wasm tests

the trait bound `adder::Proxy<VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>: ProxyObjBase` is not satisfied

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / Contracts / Wasm tests

the trait bound `VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>: multiversx_sc::api::vm_api::VMApi` is not satisfied

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / Contracts / Rust tests

the trait bound `adder::Proxy<VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>: ProxyObjBase` is not satisfied

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / Contracts / Rust tests

the trait bound `VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>: multiversx_sc::api::vm_api::VMApi` is not satisfied

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] contracts/paymaster/tests/paymaster_blackbox_test.rs#L53

error[E0277]: the trait bound `adder::Proxy<multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>: multiversx_sc::contract_base::ProxyObjBase` is not satisfied --> contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31 | 53 | callee_sc_adder_contract: AdderContract, | ^^^^^^^^^^^^^ the trait `multiversx_sc::contract_base::ProxyObjBase` is not implemented for `adder::Proxy<multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>` | = help: the trait `multiversx_sc::contract_base::ProxyObjBase` is implemented for `paymaster::Proxy<A>` note: required by a bound in `multiversx_sc_scenario::ContractInfo` --> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/multiversx-sc-scenario-0.43.4/src/facade/contract_info.rs:14:28 | 14 | pub struct ContractInfo<P: ProxyObjBase> { | ^^^^^^^^^^^^ required by this bound in `ContractInfo`
Raw output
contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31:e:error[E0277]: the trait bound `adder::Proxy<multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>: multiversx_sc::contract_base::ProxyObjBase` is not satisfied
  --> contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31
   |
53 |     callee_sc_adder_contract: AdderContract,
   |                               ^^^^^^^^^^^^^ the trait `multiversx_sc::contract_base::ProxyObjBase` is not implemented for `adder::Proxy<multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>>`
   |
   = help: the trait `multiversx_sc::contract_base::ProxyObjBase` is implemented for `paymaster::Proxy<A>`
note: required by a bound in `multiversx_sc_scenario::ContractInfo`
  --> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/multiversx-sc-scenario-0.43.4/src/facade/contract_info.rs:14:28
   |
14 | pub struct ContractInfo<P: ProxyObjBase> {
   |                            ^^^^^^^^^^^^ required by this bound in `ContractInfo`


__END__

Check failure on line 53 in contracts/paymaster/tests/paymaster_blackbox_test.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] contracts/paymaster/tests/paymaster_blackbox_test.rs#L53

error[E0277]: the trait bound `multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>: multiversx_sc::api::vm_api::VMApi` is not satisfied --> contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31 | 53 | callee_sc_adder_contract: AdderContract, | ^^^^^^^^^^^^^ the trait `multiversx_sc::api::vm_api::VMApi` is not implemented for `multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>` | = help: the following other types implement trait `multiversx_sc::api::vm_api::VMApi`: multiversx_sc::api::external_view::ev_wrapper::ExternalViewApi<A> multiversx_sc::api::uncallable::UncallableApi note: required by a bound in `adder::Proxy` --> /home/runner/work/mx-contracts-rs/mx-contracts-rs/contracts/adder/src/adder.rs:7:1 | 7 | #[multiversx_sc::contract] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Proxy` = note: this error originates in the attribute macro `multiversx_sc::contract` (in Nightly builds, run with -Z macro-backtrace for more info)
Raw output
contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31:e:error[E0277]: the trait bound `multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>: multiversx_sc::api::vm_api::VMApi` is not satisfied
  --> contracts/paymaster/tests/paymaster_blackbox_test.rs:53:31
   |
53 |     callee_sc_adder_contract: AdderContract,
   |                               ^^^^^^^^^^^^^ the trait `multiversx_sc::api::vm_api::VMApi` is not implemented for `multiversx_sc_scenario::api::VMHooksApi<multiversx_sc_scenario::api::impl_vh::static_api::StaticApiBackend>`
   |
   = help: the following other types implement trait `multiversx_sc::api::vm_api::VMApi`:
             multiversx_sc::api::external_view::ev_wrapper::ExternalViewApi<A>
             multiversx_sc::api::uncallable::UncallableApi
note: required by a bound in `adder::Proxy`
  --> /home/runner/work/mx-contracts-rs/mx-contracts-rs/contracts/adder/src/adder.rs:7:1
   |
7  | #[multiversx_sc::contract]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Proxy`
   = note: this error originates in the attribute macro `multiversx_sc::contract` (in Nightly builds, run with -Z macro-backtrace for more info)


__END__
}

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::<Vec<u8>>::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::<Vec<u8>>::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,
);
}
Binary file added contracts/paymaster/tests/test-contracts/adder.wasm
Binary file not shown.

0 comments on commit 7dd9a99

Please sign in to comment.