marco evm
Módulo0x1::evm
0x1::evmRecurso
Accountestructura
Log0Eventestructura
Log1Eventestructura
Log2Eventestructura
Log3Eventestructura
Log4EventRecurso
ContractEventConstantes
Función
send_txFunción
estimate_tx_gasFunción
depositFunción
get_move_addressFunción
queryFunción
get_storage_atFunción
executeFunción
runFunción
exist_contractFunción
add_balanceFunción
transfer_from_move_addrFunción
transfer_to_evm_addrFunción
transfer_to_move_addrFunción
create_event_if_not_existFunción
create_account_if_not_existFunción
verify_nonceFunció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
AccountCopiar
struct Account has keyCampos
balance: u256nonce: u64is_contract: boolcode: vector<u8>storage: table::Table<u256, vector<u8>>
estructuraLog0Event
Log0EventCopiar
struct Log0Event has drop, storeestructuraLog1Event
Log1EventCopiar
struct Log1Event has drop, storeestructuraLog2Event
Log2EventCopiar
struct Log2Event has drop, storeestructuraLog3Event
Log3EventCopiar
struct Log3Event has drop, storeestructuraLog4Event
Log4EventCopiar
struct Log4Event has drop, storeCampos
contract: vector<u8>data: vector<u8>topic0: vector<u8>topic1: vector<u8>topic2: vector<u8>topic3: vector<u8>
RecursoContractEvent
ContractEventCopiar
struct ContractEvent has keyCampos
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_txCopiar
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_gasCopiar
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
depositCopiar
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_addressCopiar
#[view]
public fun get_move_address(evm_addr: vector<u8>): addressImplementación
Copiar
public fun get_move_address(evm_addr: vector<u8>): address {
create_resource_address(&@aptos_framework, to_32bit(evm_addr))
}Funciónquery
queryCopiar
#[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_atCopiar
#[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
executeCopiar
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
runCopiar
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_contractCopiar
fun exist_contract(addr: address): boolImplementació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_balanceCopiar
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_addrCopiar
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_addrCopiar
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_addrCopiar
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_existCopiar
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_existCopiar
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_nonceCopiar
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_signatureCopiar
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