evm framework
Module 0x1::evm
0x1::evm
Resource
Account
Struct
Log0Event
Struct
Log1Event
Struct
Log2Event
Struct
Log3Event
Struct
Log4Event
Resource
ContractEvent
Constants
Function
send_tx
Function
estimate_tx_gas
Function
deposit
Function
get_move_address
Function
query
Function
get_storage_at
Function
execute
Function
run
Function
exist_contract
Function
add_balance
Function
transfer_from_move_addr
Function
transfer_to_evm_addr
Function
transfer_to_move_addr
Function
create_event_if_not_exist
Function
create_account_if_not_exist
Function
verify_nonce
Function
verify_signature
use 0x1::account;
use 0x1::aptos_account;
use 0x1::aptos_coin;
use 0x1::aptos_hash;
use 0x1::block;
use 0x1::coin;
use 0x1::create_signer;
use 0x1::debug;
use 0x1::event;
use 0x1::evm_util;
use 0x1::from_bcs;
use 0x1::option;
use 0x1::rlp_decode;
use 0x1::rlp_encode;
use 0x1::secp256k1;
use 0x1::signer;
use 0x1::string;
use 0x1::table;
use 0x1::timestamp;
use 0x1::vector;
Resource Account
Account
struct Account has key
Fields
balance: u256nonce: u64is_contract: boolcode: vector<u8>storage: table::Table<u256, vector<u8>>
Struct Log0Event
Log0Event
struct Log0Event has drop, store
Struct Log1Event
Log1Event
struct Log1Event has drop, store
Struct Log2Event
Log2Event
struct Log2Event has drop, store
Struct Log3Event
Log3Event
struct Log3Event has drop, store
Struct Log4Event
Log4Event
struct Log4Event has drop, store
Fields
contract: vector<u8>data: vector<u8>topic0: vector<u8>topic1: vector<u8>topic2: vector<u8>topic3: vector<u8>
Resource ContractEvent
ContractEvent
struct ContractEvent has key
Fields
log0Event: event::EventHandle<evm::Log0Event>log1Event: event::EventHandle<evm::Log1Event>log2Event: event::EventHandle<evm::Log2Event>log3Event: event::EventHandle<evm::Log3Event>log4Event: event::EventHandle<evm::Log4Event>
Constants
const U256_MAX: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
const ACCOUNT_NOT_EXIST: u64 = 10008;
const ADDR_LENGTH: u64 = 10001;
const CHAIN_ID: u64 = 336;
const CHAIN_ID_BYTES: vector<u8> = [1, 80];
const CONTRACT_DEPLOYED: u64 = 10006;
const CONTRACT_READ_ONLY: u64 = 10005;
const CONVERT_BASE: u256 = 10000000000;
const INSUFFIENT_BALANCE: u64 = 10003;
const NONCE: u64 = 10004;
const ONE_ADDR: vector<u8> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
const SIGNATURE: u64 = 10002;
const TX_NOT_SUPPORT: u64 = 10007;
const TX_TYPE_LEGACY: u64 = 1;
const ZERO_ADDR: vector<u8> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
Function send_tx
send_tx
public entry fun send_tx(sender: &signer, evm_from: vector<u8>, tx: vector<u8>, gas_bytes: vector<u8>, tx_type: u64)
Implementation
public entry fun send_tx(
sender: &signer,
evm_from: vector<u8>,
tx: vector<u8>,
gas_bytes: vector<u8>,
tx_type: u64,
) acquires Account, ContractEvent {
let gas = to_u256(gas_bytes);
if(tx_type == TX_TYPE_LEGACY) {
let decoded = decode_bytes_list(&tx);
debug::print(&decoded);
let nonce = to_u256(*vector::borrow(&decoded, 0));
let gas_price = to_u256(*vector::borrow(&decoded, 1));
let gas_limit = to_u256(*vector::borrow(&decoded, 2));
let evm_to = *vector::borrow(&decoded, 3);
let value = to_u256(*vector::borrow(&decoded, 4));
let data = *vector::borrow(&decoded, 5);
let v = (to_u256(*vector::borrow(&decoded, 6)) as u64);
let r = *vector::borrow(&decoded, 7);
let s = *vector::borrow(&decoded, 8);
let message = encode_bytes_list(vector[
u256_to_trimed_data(nonce),
u256_to_trimed_data(gas_price),
u256_to_trimed_data(gas_limit),
evm_to,
u256_to_trimed_data(value),
data,
CHAIN_ID_BYTES,
x"",
x""
]);
let message_hash = keccak256(message);
verify_signature(evm_from, message_hash, to_32bit(r), to_32bit(s), v);
execute(to_32bit(evm_from), to_32bit(evm_to), (nonce as u64), data, value);
transfer_to_move_addr(to_32bit(evm_from), address_of(sender), gas * CONVERT_BASE);
} else {
assert!(false, TX_NOT_SUPPORT);
}
}
Function estimate_tx_gas
estimate_tx_gas
public entry fun estimate_tx_gas(evm_from: vector<u8>, evm_to: vector<u8>, data: vector<u8>, value_bytes: vector<u8>, tx_type: u64)
Implementation
public entry fun estimate_tx_gas(
evm_from: vector<u8>,
evm_to: vector<u8>,
data: vector<u8>,
value_bytes: vector<u8>,
tx_type: u64,
) acquires Account, ContractEvent {
let value = to_u256(value_bytes);
if(tx_type == TX_TYPE_LEGACY) {
let address_from = create_resource_address(&@aptos_framework, to_32bit(evm_from));
assert!(exists<Account>(address_from), ACCOUNT_NOT_EXIST);
let nonce = borrow_global<Account>(create_resource_address(&@aptos_framework, to_32bit(evm_from))).nonce;
execute(to_32bit(evm_from), to_32bit(evm_to), nonce, data, value);
} else {
assert!(false, TX_NOT_SUPPORT);
}
}
Function deposit
deposit
public entry fun deposit(sender: &signer, evm_addr: vector<u8>, amount_bytes: vector<u8>)
Implementation
public entry fun deposit(sender: &signer, evm_addr: vector<u8>, amount_bytes: vector<u8>) acquires Account {
let amount = to_u256(amount_bytes);
assert!(vector::length(&evm_addr) == 20, ADDR_LENGTH);
transfer_from_move_addr(sender, to_32bit(evm_addr), amount);
}
Function get_move_address
get_move_address
#[view]
public fun get_move_address(evm_addr: vector<u8>): address
Implementation
public fun get_move_address(evm_addr: vector<u8>): address {
create_resource_address(&@aptos_framework, to_32bit(evm_addr))
}
Function query
query
#[view]
public fun query(sender: vector<u8>, contract_addr: vector<u8>, data: vector<u8>): vector<u8>
Implementation
public fun query(sender:vector<u8>, contract_addr: vector<u8>, data: vector<u8>): vector<u8> acquires Account, ContractEvent {
contract_addr = to_32bit(contract_addr);
let contract_store = borrow_global_mut<Account>(create_resource_address(&@aptos_framework, contract_addr));
run(sender, sender, contract_addr, contract_store.code, data, true, 0)
}
Function get_storage_at
get_storage_at
#[view]
public fun get_storage_at(addr: vector<u8>, slot: vector<u8>): vector<u8>
Implementation
public fun get_storage_at(addr: vector<u8>, slot: vector<u8>): vector<u8> acquires Account {
let move_address = create_resource_address(&@aptos_framework, addr);
if(exists<Account>(move_address)) {
let account_store = borrow_global<Account>(move_address);
let slot_u256 = data_to_u256(slot, 0, (vector::length(&slot) as u256));
if(table::contains(&account_store.storage, slot_u256)) {
*table::borrow(&account_store.storage, slot_u256)
} else {
vector::empty<u8>()
}
} else {
vector::empty<u8>()
}
}
Function execute
execute
fun execute(evm_from: vector<u8>, evm_to: vector<u8>, nonce: u64, data: vector<u8>, value: u256): vector<u8>
Implementation
fun execute(evm_from: vector<u8>, evm_to: vector<u8>, nonce: u64, data: vector<u8>, value: u256): vector<u8> acquires Account, ContractEvent {
let address_from = create_resource_address(&@aptos_framework, evm_from);
let address_to = create_resource_address(&@aptos_framework, evm_to);
create_account_if_not_exist(address_from);
create_account_if_not_exist(address_to);
verify_nonce(address_from, nonce);
let account_store_to = borrow_global_mut<Account>(address_to);
if(evm_to == ZERO_ADDR) {
let evm_contract = get_contract_address(evm_from, nonce);
let address_contract = create_resource_address(&@aptos_framework, evm_contract);
create_account_if_not_exist(address_contract);
create_event_if_not_exist(address_contract);
borrow_global_mut<Account>(address_contract).is_contract = true;
borrow_global_mut<Account>(address_contract).code = run(evm_from, evm_from, evm_contract, data, x"", false, value);
evm_contract
} else if(evm_to == ONE_ADDR) {
let amount = data_to_u256(data, 36, 32);
let to = to_address(slice(data, 100, 32));
transfer_to_move_addr(evm_from, to, amount);
x""
} else {
if(account_store_to.is_contract) {
run(evm_from, evm_from, evm_to, account_store_to.code, data, false, value)
} else {
transfer_to_evm_addr(evm_from, evm_to, value);
x""
}
}
}
Function run
run
fun run(sender: vector<u8>, origin: vector<u8>, evm_contract_address: vector<u8>, code: vector<u8>, data: vector<u8>, readOnly: bool, value: u256): vector<u8>
Implementation
fun run(sender: vector<u8>, origin: vector<u8>, evm_contract_address: vector<u8>, code: vector<u8>, data: vector<u8>, readOnly: bool, value: u256): vector<u8> acquires Account, ContractEvent {
let move_contract_address = create_resource_address(&@aptos_framework, evm_contract_address);
transfer_to_evm_addr(sender, evm_contract_address, value);
let stack = &mut vector::empty<u256>();
let memory = &mut vector::empty<u8>();
// let contract_store = borrow_global_mut<Account>(move_contract_address);
// let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
// let storage = simple_map::borrow_mut<vector<u8>, T>(&mut global.contracts, &contract_addr).storage;
let len = vector::length(&code);
let runtime_code = vector::empty<u8>();
let i = 0;
let ret_size = 0;
let ret_bytes = vector::empty<u8>();
while (i < len) {
let opcode = *vector::borrow(&code, i);
// debug::print(&i);
// debug::print(&opcode);
// stop
if(opcode == 0x00) {
ret_bytes = runtime_code;
break
}
else if(opcode == 0xf3) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
ret_bytes = slice(*memory, pos, len);
break
}
//add
else if(opcode == 0x01) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
if(a > 0 && b >= (U256_MAX - a + 1)) {
vector::push_back(stack, b - (U256_MAX - a + 1));
} else {
vector::push_back(stack, a + b);
};
i = i + 1;
}
//mul
else if(opcode == 0x02) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a * b);
i = i + 1;
}
//sub
else if(opcode == 0x03) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
if(a >= b) {
vector::push_back(stack, a - b);
} else {
vector::push_back(stack, U256_MAX - b + a + 1);
};
i = i + 1;
}
//div && sdiv
else if(opcode == 0x04 || opcode == 0x05) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a / b);
i = i + 1;
}
//mod && smod
else if(opcode == 0x06 || opcode == 0x07) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a % b);
i = i + 1;
}
//addmod
else if(opcode == 0x08) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
let n = vector::pop_back(stack);
vector::push_back(stack, (a + b) % n);
i = i + 1;
}
//mulmod
else if(opcode == 0x09) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
let n = vector::pop_back(stack);
vector::push_back(stack, (a * b) % n);
i = i + 1;
}
//exp
else if(opcode == 0x0a) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, power(a, b));
i = i + 1;
}
//lt
else if(opcode == 0x10) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
if(a < b) {
vector::push_back(stack, 1)
} else {
vector::push_back(stack, 0)
};
i = i + 1;
}
//gt
else if(opcode == 0x11) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
if(a > b) {
vector::push_back(stack, 1)
} else {
vector::push_back(stack, 0)
};
i = i + 1;
}
//slt
else if(opcode == 0x12) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
let(sg_a, num_a) = to_int256(a);
let(sg_b, num_b) = to_int256(b);
let value = 0;
if((sg_a && !sg_b) || (sg_a && sg_b && num_a > num_b) || (!sg_a && !sg_b && num_a < num_b)) {
value = 1
};
vector::push_back(stack, value);
i = i + 1;
}
//sgt
else if(opcode == 0x13) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
let(sg_a, num_a) = to_int256(a);
let(sg_b, num_b) = to_int256(b);
let value = 0;
if((sg_a && !sg_b) || (sg_a && sg_b && num_a < num_b) || (!sg_a && !sg_b && num_a > num_b)) {
value = 1
};
vector::push_back(stack, value);
i = i + 1;
}
//eq
else if(opcode == 0x14) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
if(a == b) {
vector::push_back(stack, 1);
} else {
vector::push_back(stack, 0);
};
i = i + 1;
}
//and
else if(opcode == 0x16) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a & b);
i = i + 1;
}
//or
else if(opcode == 0x17) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a | b);
i = i + 1;
}
//xor
else if(opcode == 0x18) {
let a = vector::pop_back(stack);
let b = vector::pop_back(stack);
vector::push_back(stack, a ^ b);
i = i + 1;
}
//not
else if(opcode == 0x19) {
// 10 1010
// 6 0101
let n = vector::pop_back(stack);
vector::push_back(stack, U256_MAX - n);
i = i + 1;
}
//shl
else if(opcode == 0x1b) {
let b = vector::pop_back(stack);
let a = vector::pop_back(stack);
if(b >= 256) {
vector::push_back(stack, 0);
} else {
vector::push_back(stack, a << (b as u8));
};
i = i + 1;
}
//shr
else if(opcode == 0x1c) {
let b = vector::pop_back(stack);
let a = vector::pop_back(stack);
if(b >= 256) {
vector::push_back(stack, 0);
} else {
vector::push_back(stack, a >> (b as u8));
};
i = i + 1;
}
//push0
else if(opcode == 0x5f) {
vector::push_back(stack, 0);
i = i + 1;
}
// push1 -> push32
else if(opcode >= 0x60 && opcode <= 0x7f) {
let n = ((opcode - 0x60) as u64);
let number = data_to_u256(code, ((i + 1) as u256), ((n + 1) as u256));
vector::push_back(stack, (number as u256));
i = i + n + 2;
}
// pop
else if(opcode == 0x50) {
vector::pop_back(stack);
i = i + 1
}
//address
else if(opcode == 0x30) {
vector::push_back(stack, data_to_u256(evm_contract_address, 0, 32));
i = i + 1;
}
//balance
else if(opcode == 0x31) {
let addr = u256_to_data(vector::pop_back(stack));
let account_store = borrow_global<Account>(create_resource_address(&@aptos_framework, addr));
vector::push_back(stack, account_store.balance);
i = i + 1;
}
//origin
else if(opcode == 0x32) {
let value = data_to_u256(origin, 0, 32);
vector::push_back(stack, value);
i = i + 1;
}
//caller
else if(opcode == 0x33) {
let value = data_to_u256(sender, 0, 32);
vector::push_back(stack, value);
i = i + 1;
}
// callvalue
else if(opcode == 0x34) {
vector::push_back(stack, value);
i = i + 1;
}
//calldataload
else if(opcode == 0x35) {
let pos = vector::pop_back(stack);
vector::push_back(stack, data_to_u256(data, pos, 32));
i = i + 1;
// block.
}
//calldatasize
else if(opcode == 0x36) {
vector::push_back(stack, (vector::length(&data) as u256));
i = i + 1;
}
//calldatacopy
else if(opcode == 0x37) {
let m_pos = vector::pop_back(stack);
let d_pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let end = d_pos + len;
// debug::print(&utf8(b"calldatacopy"));
// debug::print(&data);
while (d_pos < end) {
// debug::print(&d_pos);
// debug::print(&end);
let bytes = if(end - d_pos >= 32) {
slice(data, d_pos, 32)
} else {
slice(data, d_pos, end - d_pos)
};
// debug::print(&bytes);
mstore(memory, m_pos, bytes);
d_pos = d_pos + 32;
m_pos = m_pos + 32;
};
i = i + 1
}
//codesize
else if(opcode == 0x38) {
vector::push_back(stack, (vector::length(&code) as u256));
i = i + 1
}
//codecopy
else if(opcode == 0x39) {
let m_pos = vector::pop_back(stack);
let d_pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let end = d_pos + len;
runtime_code = slice(code, d_pos, len);
while (d_pos < end) {
let bytes = if(end - d_pos >= 32) {
slice(code, d_pos, 32)
} else {
slice(code, d_pos, end - d_pos)
};
mstore(memory, m_pos, bytes);
d_pos = d_pos + 32;
m_pos = m_pos + 32;
};
i = i + 1
}
//extcodesize
else if(opcode == 0x3b) {
let bytes = u256_to_data(vector::pop_back(stack));
let target_evm = to_32bit(slice(bytes, 12, 20));
let target_address = create_resource_address(&@aptos_framework, target_evm);
if(exists<Account>(target_address)) {
let code = borrow_global<Account>(target_address).code;
vector::push_back(stack, (vector::length(&code) as u256));
} else {
vector::push_back(stack, 0);
};
i = i + 1;
}
//returndatacopy
else if(opcode == 0x3e) {
// mstore()
let m_pos = vector::pop_back(stack);
let d_pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let bytes = slice(ret_bytes, d_pos, len);
mstore(memory, m_pos, bytes);
i = i + 1;
}
//returndatasize
else if(opcode == 0x3d) {
vector::push_back(stack, ret_size);
i = i + 1;
}
//blockhash
else if(opcode == 0x40) {
vector::push_back(stack, 0);
i = i + 1;
}
//coinbase
else if(opcode == 0x41) {
vector::push_back(stack, 0);
i = i + 1;
}
//timestamp
else if(opcode == 0x42) {
vector::push_back(stack, (now_microseconds() as u256) / 1000000);
i = i + 1;
}
//number
else if(opcode == 0x43) {
vector::push_back(stack, (block::get_current_block_height() as u256));
i = i + 1;
}
//difficulty
else if(opcode == 0x44) {
vector::push_back(stack, 0);
i = i + 1;
}
//gaslimit
else if(opcode == 0x45) {
vector::push_back(stack, 30000000);
i = i + 1;
}
//chainid
else if(opcode == 0x46) {
vector::push_back(stack, 1);
i = i + 1
}
//self balance
else if(opcode == 0x47) {
let contract_store = borrow_global_mut<Account>(move_contract_address);
vector::push_back(stack, contract_store.balance);
i = i + 1;
}
// mload
else if(opcode == 0x51) {
let pos = vector::pop_back(stack);
vector::push_back(stack, data_to_u256(slice(*memory, pos, 32), 0, 32));
i = i + 1;
}
// mstore
else if(opcode == 0x52) {
let pos = vector::pop_back(stack);
let value = vector::pop_back(stack);
mstore(memory, pos, u256_to_data(value));
// debug::print(memory);
i = i + 1;
}
//mstore8
else if(opcode == 0x53) {
let pos = vector::pop_back(stack);
let value = vector::pop_back(stack);
*vector::borrow_mut(memory, (pos as u64)) = ((value & 0xff) as u8);
// mstore(memory, pos, u256_to_data(value & 0xff));
// debug::print(memory);
i = i + 1;
}
// sload
else if(opcode == 0x54) {
let pos = vector::pop_back(stack);
let contract_store = borrow_global_mut<Account>(move_contract_address);
if(table::contains(&contract_store.storage, pos)) {
let value = *table::borrow(&mut contract_store.storage, pos);
vector::push_back(stack, data_to_u256(value, 0, 32));
} else {
vector::push_back(stack, 0);
};
i = i + 1;
}
// sstore
else if(opcode == 0x55) {
if(readOnly) {
assert!(false, CONTRACT_READ_ONLY);
};
let contract_store = borrow_global_mut<Account>(move_contract_address);
let pos = vector::pop_back(stack);
let value = vector::pop_back(stack);
table::upsert(&mut contract_store.storage, pos, u256_to_data(value));
// debug::print(&utf8(b"sstore"));
// debug::print(&evm_contract_address);
// debug::print(&pos);
// debug::print(&value);
i = i + 1;
}
//dup1 -> dup16
else if(opcode >= 0x80 && opcode <= 0x8f) {
let size = vector::length(stack);
let value = *vector::borrow(stack, size - ((opcode - 0x80 + 1) as u64));
vector::push_back(stack, value);
i = i + 1;
}
//swap1 -> swap16
else if(opcode >= 0x90 && opcode <= 0x9f) {
let size = vector::length(stack);
vector::swap(stack, size - 1, size - ((opcode - 0x90 + 2) as u64));
i = i + 1;
}
//iszero
else if(opcode == 0x15) {
let value = vector::pop_back(stack);
if(value == 0) {
vector::push_back(stack, 1)
} else {
vector::push_back(stack, 0)
};
i = i + 1;
}
//jump
else if(opcode == 0x56) {
let dest = vector::pop_back(stack);
i = (dest as u64) + 1
}
//jumpi
else if(opcode == 0x57) {
let dest = vector::pop_back(stack);
let condition = vector::pop_back(stack);
if(condition > 0) {
i = (dest as u64) + 1
} else {
i = i + 1
}
}
//gas
else if(opcode == 0x5a) {
vector::push_back(stack, 0);
i = i + 1
}
//jump dest (no action, continue execution)
else if(opcode == 0x5b) {
i = i + 1
}
//sha3
else if(opcode == 0x20) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let bytes = slice(*memory, pos, len);
// debug::print(&utf8(b"sha3"));
// debug::print(&bytes);
let value = data_to_u256(keccak256(bytes), 0, 32);
// debug::print(&value);
vector::push_back(stack, value);
i = i + 1
}
//call 0xf1 static call 0xfa delegate call 0xf4
else if(opcode == 0xf1 || opcode == 0xfa || opcode == 0xf4) {
let readOnly = if (opcode == 0xfa) true else false;
let _gas = vector::pop_back(stack);
let evm_dest_addr = to_32bit(u256_to_data(vector::pop_back(stack)));
let move_dest_addr = create_resource_address(&@aptos_framework, evm_dest_addr);
let msg_value = if (opcode == 0xf1) vector::pop_back(stack) else 0;
let m_pos = vector::pop_back(stack);
let m_len = vector::pop_back(stack);
let ret_pos = vector::pop_back(stack);
let ret_len = vector::pop_back(stack);
// debug::print(&utf8(b"call 222"));
// debug::print(&opcode);
// debug::print(&dest_addr);
if (exists<Account>(move_dest_addr)) {
let ret_end = ret_len + ret_pos;
let params = slice(*memory, m_pos, m_len);
let account_store_dest = borrow_global_mut<Account>(move_dest_addr);
let target = if (opcode == 0xf4) evm_contract_address else evm_dest_addr;
let from = if (opcode == 0xf4) sender else evm_contract_address;
// debug::print(&utf8(b"call"));
// debug::print(¶ms);
// if(opcode == 0xf4) {
// debug::print(&utf8(b"delegate call"));
// debug::print(&sender);
// debug::print(&target);
// };
ret_bytes = run(from, sender, target, account_store_dest.code, params, readOnly, msg_value);
ret_size = (vector::length(&ret_bytes) as u256);
let index = 0;
// if(opcode == 0xf4) {
// storage = simple_map::borrow_mut<vector<u8>, T>(&mut global.contracts, &contract_addr).storage;
// };
while (ret_pos < ret_end) {
let bytes = if (ret_end - ret_pos >= 32) {
slice(ret_bytes, index, 32)
} else {
slice(ret_bytes, index, ret_end - ret_pos)
};
mstore(memory, ret_pos, bytes);
ret_pos = ret_pos + 32;
index = index + 32;
};
vector::push_back(stack, 1);
} else {
if (opcode == 0xfa) {
vector::push_back(stack, 0);
} else {
transfer_to_evm_addr(evm_contract_address, evm_dest_addr, msg_value);
}
};
// debug::print(&opcode);
i = i + 1
}
//create
else if(opcode == 0xf0) {
if(readOnly) {
assert!(false, CONTRACT_READ_ONLY);
};
let msg_value = vector::pop_back(stack);
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let new_codes = slice(*memory, pos, len);
let contract_store = borrow_global_mut<Account>(move_contract_address);
let nonce = contract_store.nonce;
// must be 20 bytes
let new_evm_contract_addr = get_contract_address(evm_contract_address, nonce);
debug::print(&utf8(b"create start"));
debug::print(&new_evm_contract_addr);
let new_move_contract_addr = create_resource_address(&@aptos_framework, new_evm_contract_addr);
contract_store.nonce = contract_store.nonce + 1;
debug::print(&exists<Account>(new_move_contract_addr));
assert!(!exist_contract(new_move_contract_addr), CONTRACT_DEPLOYED);
create_account_if_not_exist(new_move_contract_addr);
create_event_if_not_exist(new_move_contract_addr);
// let new_contract_store = borrow_global_mut<Account>(new_move_contract_addr);
borrow_global_mut<Account>(move_contract_address).nonce = 1;
borrow_global_mut<Account>(move_contract_address).is_contract = true;
borrow_global_mut<Account>(move_contract_address).code = run(evm_contract_address, sender, new_evm_contract_addr, new_codes, x"", false, msg_value);
debug::print(&utf8(b"create end"));
ret_size = 32;
ret_bytes = new_evm_contract_addr;
vector::push_back(stack, data_to_u256(new_evm_contract_addr, 0, 32));
i = i + 1
}
//create2
else if(opcode == 0xf5) {
if(readOnly) {
assert!(false, CONTRACT_READ_ONLY);
};
let msg_value = vector::pop_back(stack);
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let salt = u256_to_data(vector::pop_back(stack));
let new_codes = slice(*memory, pos, len);
let p = vector::empty<u8>();
// let contract_store = ;
vector::append(&mut p, x"ff");
// must be 20 bytes
vector::append(&mut p, slice(evm_contract_address, 12, 20));
vector::append(&mut p, salt);
vector::append(&mut p, keccak256(new_codes));
let new_evm_contract_addr = to_32bit(slice(keccak256(p), 12, 20));
let new_move_contract_addr = create_resource_address(&@aptos_framework, new_evm_contract_addr);
debug::print(&utf8(b"create2 start"));
debug::print(&new_evm_contract_addr);
debug::print(&exists<Account>(new_move_contract_addr));
assert!(!exist_contract(new_move_contract_addr), CONTRACT_DEPLOYED);
create_account_if_not_exist(new_move_contract_addr);
create_event_if_not_exist(new_move_contract_addr);
// debug::print(&p);
// debug::print(&new_codes);
// debug::print(&new_contract_addr);
borrow_global_mut<Account>(move_contract_address).nonce = borrow_global_mut<Account>(move_contract_address).nonce + 1;
// let new_contract_store = borrow_global_mut<Account>(new_move_contract_addr);
borrow_global_mut<Account>(new_move_contract_addr).nonce = 1;
borrow_global_mut<Account>(new_move_contract_addr).is_contract = true;
borrow_global_mut<Account>(new_move_contract_addr).code = run(evm_contract_address, sender, new_evm_contract_addr, new_codes, x"", false, msg_value);
// new_contract_store.code = code;
ret_size = 32;
ret_bytes = new_evm_contract_addr;
vector::push_back(stack, data_to_u256(new_evm_contract_addr,0, 32));
i = i + 1
}
//revert
else if(opcode == 0xfd) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let bytes = slice(*memory, pos, len);
debug::print(&bytes);
// debug::print(&pos);
// debug::print(&len);
// debug::print(memory);
i = i + 1;
assert!(false, (opcode as u64));
}
//log0
else if(opcode == 0xa0) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let data = slice(*memory, pos, len);
let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
event::emit_event<Log0Event>(
&mut event_store.log0Event,
Log0Event{
contract: evm_contract_address,
data,
},
);
i = i + 1
}
//log1
else if(opcode == 0xa1) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let data = slice(*memory, pos, len);
let topic0 = u256_to_data(vector::pop_back(stack));
let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
event::emit_event<Log1Event>(
&mut event_store.log1Event,
Log1Event{
contract: evm_contract_address,
data,
topic0,
},
);
i = i + 1
}
//log2
else if(opcode == 0xa2) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let data = slice(*memory, pos, len);
let topic0 = u256_to_data(vector::pop_back(stack));
let topic1 = u256_to_data(vector::pop_back(stack));
let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
event::emit_event<Log2Event>(
&mut event_store.log2Event,
Log2Event{
contract: evm_contract_address,
data,
topic0,
topic1
},
);
i = i + 1
}
//log3
else if(opcode == 0xa3) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let data = slice(*memory, pos, len);
let topic0 = u256_to_data(vector::pop_back(stack));
let topic1 = u256_to_data(vector::pop_back(stack));
let topic2 = u256_to_data(vector::pop_back(stack));
let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
event::emit_event<Log3Event>(
&mut event_store.log3Event,
Log3Event{
contract: evm_contract_address,
data,
topic0,
topic1,
topic2
},
);
i = i + 1
}
//log4
else if(opcode == 0xa4) {
let pos = vector::pop_back(stack);
let len = vector::pop_back(stack);
let data = slice(*memory, pos, len);
let topic0 = u256_to_data(vector::pop_back(stack));
let topic1 = u256_to_data(vector::pop_back(stack));
let topic2 = u256_to_data(vector::pop_back(stack));
let topic3 = u256_to_data(vector::pop_back(stack));
let event_store = borrow_global_mut<ContractEvent>(move_contract_address);
event::emit_event<Log4Event>(
&mut event_store.log4Event,
Log4Event{
contract: evm_contract_address,
data,
topic0,
topic1,
topic2,
topic3
},
);
i = i + 1
}
else {
assert!(false, (opcode as u64));
};
// debug::print(stack);
// debug::print(&vector::length(stack));
};
// simple_map::borrow_mut<vector<u8>, T>(&mut global.contracts, &contract_addr).storage = storage;
ret_bytes
}
Function exist_contract
exist_contract
fun exist_contract(addr: address): bool
Implementation
fun exist_contract(addr: address): bool acquires Account {
exists<Account>(addr) && (vector::length(&borrow_global<Account>(addr).code) > 0)
}
Function add_balance
add_balance
fun add_balance(addr: address, amount: u256)
Implementation
fun add_balance(addr: address, amount: u256) acquires Account {
create_account_if_not_exist(addr);
if(amount > 0) {
let account_store = borrow_global_mut<Account>(addr);
account_store.balance = account_store.balance + amount;
}
}
Function transfer_from_move_addr
transfer_from_move_addr
fun transfer_from_move_addr(signer: &signer, evm_to: vector<u8>, amount: u256)
Implementation
fun transfer_from_move_addr(signer: &signer, evm_to: vector<u8>, amount: u256) acquires Account {
if(amount > 0) {
let move_to = create_resource_address(&@aptos_framework, evm_to);
create_account_if_not_exist(move_to);
coin::transfer<AptosCoin>(signer, move_to, ((amount / CONVERT_BASE) as u64));
let account_store_to = borrow_global_mut<Account>(move_to);
account_store_to.balance = account_store_to.balance + amount;
}
}
Function transfer_to_evm_addr
transfer_to_evm_addr
fun transfer_to_evm_addr(evm_from: vector<u8>, evm_to: vector<u8>, amount: u256)
Implementation
fun transfer_to_evm_addr(evm_from: vector<u8>, evm_to: vector<u8>, amount: u256) acquires Account {
if(amount > 0) {
let move_from = create_resource_address(&@aptos_framework, evm_from);
let move_to = create_resource_address(&@aptos_framework, evm_to);
let account_store_from = borrow_global_mut<Account>(move_from);
assert!(account_store_from.balance >= amount, INSUFFIENT_BALANCE);
account_store_from.balance = account_store_from.balance - amount;
let account_store_to = borrow_global_mut<Account>(move_to);
account_store_to.balance = account_store_to.balance + amount;
let signer = create_signer(move_from);
coin::transfer<AptosCoin>(&signer, move_to, ((amount / CONVERT_BASE) as u64));
}
}
Function transfer_to_move_addr
transfer_to_move_addr
fun transfer_to_move_addr(evm_from: vector<u8>, move_to: address, amount: u256)
Implementation
fun transfer_to_move_addr(evm_from: vector<u8>, move_to: address, amount: u256) acquires Account {
if(amount > 0) {
let move_from = create_resource_address(&@aptos_framework, evm_from);
let account_store_from = borrow_global_mut<Account>(move_from);
assert!(account_store_from.balance >= amount, INSUFFIENT_BALANCE);
account_store_from.balance = account_store_from.balance - amount;
let signer = create_signer(move_from);
coin::transfer<AptosCoin>(&signer, move_to, ((amount / CONVERT_BASE) as u64));
}
}
Function create_event_if_not_exist
create_event_if_not_exist
fun create_event_if_not_exist(addr: address)
Implementation
fun create_event_if_not_exist(addr: address) {
if(!exists<ContractEvent>(addr)) {
let signer = create_signer(addr);
move_to(&signer, ContractEvent {
log0Event: new_event_handle<Log0Event>(&signer),
log1Event: new_event_handle<Log1Event>(&signer),
log2Event: new_event_handle<Log2Event>(&signer),
log3Event: new_event_handle<Log3Event>(&signer),
log4Event: new_event_handle<Log4Event>(&signer),
})
}
}
Function create_account_if_not_exist
create_account_if_not_exist
fun create_account_if_not_exist(addr: address)
Implementation
fun create_account_if_not_exist(addr: address) {
if(!exists<Account>(addr)) {
if(!exists_at(addr)) {
create_account(addr);
};
let signer = create_signer(addr);
coin::register<AptosCoin>(&signer);
move_to(&signer, Account {
code: vector::empty(),
storage: table::new<u256, vector<u8>>(),
balance: 0,
is_contract: false,
nonce: 0
})
};
}
Function verify_nonce
verify_nonce
fun verify_nonce(addr: address, nonce: u64)
Implementation
fun verify_nonce(addr: address, nonce: u64) acquires Account {
let coin_store_from = borrow_global_mut<Account>(addr);
assert!(coin_store_from.nonce == nonce, NONCE);
coin_store_from.nonce = coin_store_from.nonce + 1;
}
Function verify_signature
verify_signature
fun verify_signature(from: vector<u8>, message_hash: vector<u8>, r: vector<u8>, s: vector<u8>, v: u64)
Implementation
fun verify_signature(from: vector<u8>, message_hash: vector<u8>, r: vector<u8>, s: vector<u8>, v: u64) {
let input_bytes = r;
vector::append(&mut input_bytes, s);
let signature = ecdsa_signature_from_bytes(input_bytes);
let recovery_id = ((v - (CHAIN_ID * 2) - 35) as u8);
let pk_recover = ecdsa_recover(message_hash, recovery_id, &signature);
let pk = keccak256(ecdsa_raw_public_key_to_bytes(borrow(&pk_recover)));
debug::print(&slice(pk, 12, 20));
assert!(slice(pk, 12, 20) == from, SIGNATURE);
}
Last updated