Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ink_env::pay_with_call! helper macro for off-chain emulation of sending payments with contract msg calls #1379

Merged
merged 14 commits into from
Sep 13, 2022
Merged
36 changes: 36 additions & 0 deletions crates/env/src/engine/off_chain/test_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,42 @@ where
})
}

/// Transfers value from the caller account to the contract.
HCastano marked this conversation as resolved.
Show resolved Hide resolved
pub fn transfer_in<T>(value: T::Balance)
where
T: Environment<Balance = u128>, // Just temporary for the MVP!
{
<EnvInstance as OnInstance>::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.
Expand Down
14 changes: 14 additions & 0 deletions crates/env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,17 @@ cfg_if::cfg_if! {
}
}
}

cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
#[macro_export]
/// Prepend contract message call with value transfer. Used for tests in off-chain environment.
macro_rules! pay_with_call {
($con:ident . $msg:ident ( $($params:ty)? ) , $amt:expr) => {{
use ink_env::test::transfer_in;
transfer_in::<Environment>($amt);
$con.$msg($($params:ty)?)
}}
HCastano marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
23 changes: 17 additions & 6 deletions examples/contract-transfer/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub mod give_me {
mod tests {
use super::*;
use ink_lang as ink;
use ink_lang::codegen::Env;
HCastano marked this conversation as resolved.
Show resolved Hide resolved

#[ink::test]
fn transfer_works() {
Expand Down Expand Up @@ -104,17 +105,27 @@ pub mod give_me {
// 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::<ink_env::DefaultEnvironment>(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);
HCastano marked this conversation as resolved.
Show resolved Hide resolved

// 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]
Expand Down