Implement KIP4: create2 for wasm (#9277)
* Basic implementation for kip4 * Add KIP-4 config flags * typo: docs fix * Fix args offset * Add tests for create2 * tests: evm * Update wasm-tests and fix all gas costs * Update wasm-tests * Update wasm-tests and fix gas costs
This commit is contained in:
@@ -321,7 +321,7 @@ impl<'a> Runtime<'a> {
|
||||
if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); }
|
||||
Ok(self.gas_limit - self.gas_counter)
|
||||
}
|
||||
|
||||
|
||||
/// General gas charging extern.
|
||||
fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||
let amount: u32 = args.nth_checked(0)?;
|
||||
@@ -511,29 +511,7 @@ impl<'a> Runtime<'a> {
|
||||
self.return_u256_ptr(args.nth_checked(0)?, val)
|
||||
}
|
||||
|
||||
/// Creates a new contract
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue>
|
||||
{
|
||||
//
|
||||
// method signature:
|
||||
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let code_ptr: u32 = args.nth_checked(1)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result<RuntimeValue> {
|
||||
let code = self.memory.get(code_ptr, code_len as usize)?;
|
||||
|
||||
self.adjusted_charge(|schedule| schedule.create_gas as u64)?;
|
||||
@@ -543,7 +521,7 @@ impl<'a> Runtime<'a> {
|
||||
* U256::from(self.ext.schedule().wasm().opcodes_mul)
|
||||
/ U256::from(self.ext.schedule().wasm().opcodes_div);
|
||||
|
||||
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
|
||||
match self.ext.create(&gas_left, &endowment, &code, scheme) {
|
||||
vm::ContractCreateResult::Created(address, gas_left) => {
|
||||
self.memory.set(result_ptr, &*address)?;
|
||||
self.gas_counter = self.gas_limit -
|
||||
@@ -571,6 +549,59 @@ impl<'a> Runtime<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new contract
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
|
||||
//
|
||||
// method signature:
|
||||
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let code_ptr: u32 = args.nth_checked(1)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash)
|
||||
}
|
||||
|
||||
/// Creates a new contract using FromSenderSaltAndCodeHash scheme
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * salt - salt to be used in contract creation address
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create2(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
|
||||
//
|
||||
// method signature:
|
||||
// fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE2");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into();
|
||||
trace!(target: "wasm", " salt: {:?}", salt);
|
||||
let code_ptr: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(4)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt))
|
||||
}
|
||||
|
||||
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
|
||||
{
|
||||
trace!(target: "wasm", "Contract debug message: {}", {
|
||||
@@ -744,6 +775,7 @@ mod ext_impl {
|
||||
SENDER_FUNC => void!(self.sender(args)),
|
||||
ORIGIN_FUNC => void!(self.origin(args)),
|
||||
ELOG_FUNC => void!(self.elog(args)),
|
||||
CREATE2_FUNC => some!(self.create2(args)),
|
||||
_ => panic!("env module doesn't provide function at index {}", index),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user