evm framework

Module 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

struct Account has key
Fields

balance: u256nonce: u64is_contract: boolcode: vector<u8>storage: table::Table<u256, vector<u8>>

Struct Log0Event

struct Log0Event has drop, store
Fields

contract: vector<u8>data: vector<u8>

Struct Log1Event

struct Log1Event has drop, store
Fields

contract: vector<u8>data: vector<u8>topic0: vector<u8>

Struct Log2Event

struct Log2Event has drop, store
Fields

contract: vector<u8>data: vector<u8>topic0: vector<u8>topic1: vector<u8>

Struct Log3Event

struct Log3Event has drop, store
Fields

contract: vector<u8>data: vector<u8>topic0: vector<u8>topic1: vector<u8>topic2: vector<u8>

Struct 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

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

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

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

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

#[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

#[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

#[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

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

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

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

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

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

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

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

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

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

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

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