marco evm
Módulo0x1::evm
0x1::evm
Recurso
Account
estructura
Log0Event
estructura
Log1Event
estructura
Log2Event
estructura
Log3Event
estructura
Log4Event
Recurso
ContractEvent
Constantes
Función
send_tx
Función
estimate_tx_gas
Función
deposit
Función
get_move_address
Función
query
Función
get_storage_at
Función
execute
Función
run
Función
exist_contract
Función
add_balance
Función
transfer_from_move_addr
Función
transfer_to_evm_addr
Función
transfer_to_move_addr
Función
create_event_if_not_exist
Función
create_account_if_not_exist
Función
verify_nonce
Función
verify_signature
Copiar
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;
RecursoAccount
Account
Copiar
struct Account has key
Campos
balance: u256nonce: u64is_contract: boolcode: vector<u8>storage: table::Table<u256, vector<u8>>
estructuraLog0Event
Log0Event
Copiar
struct Log0Event has drop, store
estructuraLog1Event
Log1Event
Copiar
struct Log1Event has drop, store
estructuraLog2Event
Log2Event
Copiar
struct Log2Event has drop, store
estructuraLog3Event
Log3Event
Copiar
struct Log3Event has drop, store
estructuraLog4Event
Log4Event
Copiar
struct Log4Event has drop, store
Campos
contract: vector<u8>data: vector<u8>topic0: vector<u8>topic1: vector<u8>topic2: vector<u8>topic3: vector<u8>
RecursoContractEvent
ContractEvent
Copiar
struct ContractEvent has key
Campos
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>
Constantes
Copiar
const U256_MAX: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
Copiar
const ACCOUNT_NOT_EXIST: u64 = 10008;
Copiar
const ADDR_LENGTH: u64 = 10001;
Copiar
const CHAIN_ID: u64 = 336;
Copiar
const CHAIN_ID_BYTES: vector<u8> = [1, 80];
Copiar
const CONTRACT_DEPLOYED: u64 = 10006;
Copiar
const CONTRACT_READ_ONLY: u64 = 10005;
Copiar
const CONVERT_BASE: u256 = 10000000000;
Copiar
const INSUFFIENT_BALANCE: u64 = 10003;
Copiar
const NONCE: u64 = 10004;
Copiar
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];
Copiar
const SIGNATURE: u64 = 10002;
Copiar
const TX_NOT_SUPPORT: u64 = 10007;
Copiar
const TX_TYPE_LEGACY: u64 = 1;
Copiar
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];
Funciónsend_tx
send_tx
Copiar
public entry fun send_tx(sender: &signer, evm_from: vector<u8>, tx: vector<u8>, gas_bytes: vector<u8>, tx_type: u64)
Implementación
Copiar
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);
}
}
Funciónestimate_tx_gas
estimate_tx_gas
Copiar
public entry fun estimate_tx_gas(evm_from: vector<u8>, evm_to: vector<u8>, data: vector<u8>, value_bytes: vector<u8>, tx_type: u64)
Implementación
Copiar
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);
}
}
Funcióndeposit
deposit
Copiar
public entry fun deposit(sender: &signer, evm_addr: vector<u8>, amount_bytes: vector<u8>)
Implementación
Copiar
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);
}
Funciónget_move_address
get_move_address
Copiar
#[view]
public fun get_move_address(evm_addr: vector<u8>): address
Implementación
Copiar
public fun get_move_address(evm_addr: vector<u8>): address {
create_resource_address(&@aptos_framework, to_32bit(evm_addr))
}
Funciónquery
query
Copiar
#[view]
public fun query(sender: vector<u8>, contract_addr: vector<u8>, data: vector<u8>): vector<u8>
Implementación
Copiar
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)
}
Funciónget_storage_at
get_storage_at
Copiar
#[view]
public fun get_storage_at(addr: vector<u8>, slot: vector<u8>): vector<u8>
Implementación
Copiar
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>()
}
}
Funciónexecute
execute
Copiar
fun execute(evm_from: vector<u8>, evm_to: vector<u8>, nonce: u64, data: vector<u8>, value: u256): vector<u8>
Implementación
Copiar
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""
}
}
}
Funciónrun
run
Copiar
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>
Implementación
Copiar
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
}
Funciónexist_contract
exist_contract
Copiar
fun exist_contract(addr: address): bool
Implementación
Copiar
fun exist_contract(addr: address): bool acquires Account {
exists<Account>(addr) && (vector::length(&borrow_global<Account>(addr).code) > 0)
}
Funciónadd_balance
add_balance
Copiar
fun add_balance(addr: address, amount: u256)
Implementación
Copiar
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;
}
}
Funcióntransfer_from_move_addr
transfer_from_move_addr
Copiar
fun transfer_from_move_addr(signer: &signer, evm_to: vector<u8>, amount: u256)
Implementación
Copiar
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;
}
}
Funcióntransfer_to_evm_addr
transfer_to_evm_addr
Copiar
fun transfer_to_evm_addr(evm_from: vector<u8>, evm_to: vector<u8>, amount: u256)
Implementación
Copiar
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));
}
}
Funcióntransfer_to_move_addr
transfer_to_move_addr
Copiar
fun transfer_to_move_addr(evm_from: vector<u8>, move_to: address, amount: u256)
Implementación
Copiar
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));
}
}
Funcióncreate_event_if_not_exist
create_event_if_not_exist
Copiar
fun create_event_if_not_exist(addr: address)
Implementación
Copiar
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),
})
}
}
Funcióncreate_account_if_not_exist
create_account_if_not_exist
Copiar
fun create_account_if_not_exist(addr: address)
Implementación
Copiar
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
})
};
}
Funciónverify_nonce
verify_nonce
Copiar
fun verify_nonce(addr: address, nonce: u64)
Implementación
Copiar
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;
}
Funciónverify_signature
verify_signature
Copiar
fun verify_signature(from: vector<u8>, message_hash: vector<u8>, r: vector<u8>, s: vector<u8>, v: u64)
Implementación
Copiar
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