Add ext_transfer call (#5169)

* contracts: Add ext_transfer call

This call allows contracts to send balance to any account
contract or not. Previously, the only way to do that was
though ext_call.

* Apply suggestions from code review

Co-Authored-By: Nikolay Volf <nikvolf@gmail.com>

* The define_env! macro does not allow for trailing comma

* Update frame/contracts/src/exec.rs

Co-Authored-By: Nikolay Volf <nikvolf@gmail.com>

* Bump spec version

* Do not use nested gas meter

* Use explicit 0 or 1 as return value

* Remove superflous intermediate binding

Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
Alexander Theißen
2020-03-14 12:49:22 +01:00
committed by GitHub
parent 7e2cd0edee
commit b817763ea9
5 changed files with 158 additions and 4 deletions
@@ -405,6 +405,36 @@ define_env!(Env, <E: Ext>,
}
},
// Transfer some value to another account.
//
// If the value transfer was succesful zero is returned. Otherwise one is returned.
// The scratch buffer is not touched. The receiver can be a plain account or
// a contract.
//
// - account_ptr: a pointer to the address of the beneficiary account
// Should be decodable as an `T::AccountId`. Traps otherwise.
// - account_len: length of the address buffer.
// - value_ptr: a pointer to the buffer with value, how much value to send.
// Should be decodable as a `T::Balance`. Traps otherwise.
// - value_len: length of the value buffer.
ext_transfer(
ctx,
account_ptr: u32,
account_len: u32,
value_ptr: u32,
value_len: u32
) -> u32 => {
let callee: <<E as Ext>::T as frame_system::Trait>::AccountId =
read_sandbox_memory_as(ctx, account_ptr, account_len)?;
let value: BalanceOf<<E as Ext>::T> =
read_sandbox_memory_as(ctx, value_ptr, value_len)?;
match ctx.ext.transfer(&callee, value, ctx.gas_meter) {
Ok(_) => Ok(0),
Err(_) => Ok(1),
}
},
// Make a call to another contract.
//
// If the called contract runs to completion, then this returns the status code the callee