diff --git a/crates/env/src/engine/off_chain/test_api.rs b/crates/env/src/engine/off_chain/test_api.rs index 4d73be03ac3..09f9c82ad2d 100644 --- a/crates/env/src/engine/off_chain/test_api.rs +++ b/crates/env/src/engine/off_chain/test_api.rs @@ -200,6 +200,8 @@ where } /// Sets the value transferred from the caller to the callee as part of the call. +/// +/// Please note that the acting accounts should be set with [`set_caller()`] and [`set_callee()`] beforehand. pub fn set_value_transferred(value: T::Balance) where T: Environment, // Just temporary for the MVP! @@ -209,6 +211,44 @@ where }) } +/// Transfers value from the caller account to the contract. +/// +/// Please note that the acting accounts should be set with [`set_caller()`] and [`set_callee()`] beforehand. +pub fn transfer_in(value: T::Balance) +where + T: Environment, // Just temporary for the MVP! +{ + ::on_instance(|instance| { + let caller = instance + .engine + .exec_context + .caller + .as_ref() + .expect("no caller has been set") + .as_bytes() + .to_vec(); + + let caller_old_balance = instance + .engine + .get_balance(caller.clone()) + .unwrap_or_default(); + + let callee = instance.engine.get_callee(); + let contract_old_balance = instance + .engine + .get_balance(callee.clone()) + .unwrap_or_default(); + + instance + .engine + .set_balance(caller, caller_old_balance - value); + instance + .engine + .set_balance(callee, contract_old_balance + value); + instance.engine.set_value_transferred(value); + }); +} + /// Returns the amount of storage cells used by the account `account_id`. /// /// Returns `None` if the `account_id` is non-existent. @@ -355,3 +395,12 @@ pub fn assert_contract_termination( assert_eq!(value_transferred, expected_value_transferred_to_beneficiary); assert_eq!(beneficiary, expected_beneficiary); } + +/// Prepend contract message call with value transfer. Used for tests in off-chain environment. +#[macro_export] +macro_rules! pay_with_call { + ($contract:ident . $message:ident ( $($params:ty)? ) , $amount:expr) => {{ + $crate::test::transfer_in::($amount); + $contract.$message($($params:ty)?) + }} +} diff --git a/examples/contract-transfer/lib.rs b/examples/contract-transfer/lib.rs index a46da79f193..27e419dadd9 100644 --- a/examples/contract-transfer/lib.rs +++ b/examples/contract-transfer/lib.rs @@ -101,20 +101,31 @@ pub mod give_me { #[ink::test] fn test_transferred_value() { + use ink_lang::codegen::Env; // given let accounts = default_accounts(); let give_me = create_contract(100); + let contract_account = give_me.env().account_id(); // when - // Push the new execution context which sets Eve as caller and - // the `mock_transferred_value` as the value which the contract - // will see as transferred to it. + // Push the new execution context which sets initial balances and + // sets Eve as the caller + set_balance(accounts.eve, 100); + set_balance(contract_account, 0); set_sender(accounts.eve); - ink_env::test::set_value_transferred::(10); // then - // there must be no panic - give_me.was_it_ten(); + // we use helper macro to emulate method invocation coming with payment, + // and there must be no panic + ink_env::pay_with_call!(give_me.was_it_ten(), 10); + + // and + // balances should be changed properly + let contract_new_balance = get_balance(contract_account); + let caller_new_balance = get_balance(accounts.eve); + + assert_eq!(caller_new_balance, 100 - 10); + assert_eq!(contract_new_balance, 10); } #[ink::test]