Copy 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
}