Skip to content

Commit c7cae37

Browse files
committed
Merge commit '595971d' into elmato/merge-add-eth-get-log-test-to-main
2 parents dbe52a1 + 595971d commit c7cae37

File tree

5 files changed

+283
-2
lines changed

5 files changed

+283
-2
lines changed

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ configure_file(defertest.wasm . COPYONLY)
1111
configure_file(defertest.abi . COPYONLY)
1212
configure_file(defertest2.wasm . COPYONLY)
1313
configure_file(defertest2.abi . COPYONLY)
14+
configure_file(evmbridge.wasm . COPYONLY)
15+
configure_file(evmbridge.abi . COPYONLY)
16+

tests/evmbridge.abi

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
3+
"version": "eosio::abi/1.2",
4+
"types": [
5+
{
6+
"new_type_name": "bridge_message",
7+
"type": "variant_bridge_message_v0"
8+
}
9+
],
10+
"structs": [
11+
{
12+
"name": "bridge_message_v0",
13+
"base": "",
14+
"fields": [
15+
{
16+
"name": "receiver",
17+
"type": "name"
18+
},
19+
{
20+
"name": "sender",
21+
"type": "bytes"
22+
},
23+
{
24+
"name": "timestamp",
25+
"type": "time_point"
26+
},
27+
{
28+
"name": "value",
29+
"type": "bytes"
30+
},
31+
{
32+
"name": "data",
33+
"type": "bytes"
34+
}
35+
]
36+
},
37+
{
38+
"name": "onbridgemsg",
39+
"base": "",
40+
"fields": [
41+
{
42+
"name": "message",
43+
"type": "bridge_message"
44+
}
45+
]
46+
}
47+
],
48+
"actions": [
49+
{
50+
"name": "onbridgemsg",
51+
"type": "onbridgemsg",
52+
"ricardian_contract": ""
53+
}
54+
],
55+
"tables": [],
56+
"ricardian_clauses": [],
57+
"variants": [
58+
{
59+
"name": "variant_bridge_message_v0",
60+
"types": ["bridge_message_v0"]
61+
}
62+
],
63+
"action_results": []
64+
}

tests/evmbridge.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include <vector>
2+
#include <variant>
3+
#include <eosio/eosio.hpp>
4+
#include <eosio/contract.hpp>
5+
6+
using namespace eosio;
7+
using namespace std;
8+
9+
extern "C" {
10+
__attribute__((eosio_wasm_import))
11+
void set_action_return_value(void*, size_t);
12+
13+
__attribute__((eosio_wasm_import))
14+
uint64_t get_sender();
15+
}
16+
17+
typedef std::vector<char> bytes;
18+
19+
struct bridge_message_v0 {
20+
name receiver;
21+
bytes sender;
22+
time_point timestamp;
23+
bytes value;
24+
bytes data;
25+
26+
EOSLIB_SERIALIZE(bridge_message_v0, (receiver)(sender)(timestamp)(value)(data));
27+
};
28+
29+
using bridge_message = std::variant<bridge_message_v0>;
30+
31+
class [[eosio::contract("evmbridge")]] evmbridge : public contract {
32+
public:
33+
using contract::contract;
34+
[[eosio::action]] void onbridgemsg(const bridge_message& message);
35+
36+
37+
class contract_actions {
38+
public:
39+
void call(eosio::name from, const bytes &to, const bytes& value, const bytes &data, uint64_t gas_limit);
40+
void assertnonce(eosio::name account, uint64_t next_nonce);
41+
};
42+
43+
using call_action = action_wrapper<"call"_n, &contract_actions::call>;
44+
};
45+
46+
void evmbridge::onbridgemsg(const bridge_message& message) {
47+
const bridge_message_v0 &msg = std::get<bridge_message_v0>(message);
48+
const char method[4] = {'\x00','\x8f','\xcf','\x3e'}; // function assertdata(uint256) payable
49+
50+
uint8_t value_buffer[32] = {};
51+
52+
if (msg.data.size() >= 32) {
53+
std::copy(msg.data.end() - 32, msg.data.end(), value_buffer);
54+
}
55+
56+
bytes call_data;
57+
call_data.reserve(4 + 32);
58+
call_data.insert(call_data.end(), method, method + 4);
59+
call_data.insert(call_data.end(), value_buffer, value_buffer + 32);
60+
61+
call_action call_act("eosio.evm"_n, {{get_self(), "active"_n}});
62+
63+
bytes value;
64+
value.resize(32, 0);
65+
value[31] = 100;
66+
67+
call_act.send(get_self() /*from*/, msg.sender /*to*/, value /*value*/, call_data /*data*/, 100000 /*gas_limit*/);
68+
}
69+

tests/evmbridge.wasm

6.93 KB
Binary file not shown.

tests/nodeos_eos_evm_test.py

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ def prefix_0x(hexstr):
107107
evmRPCPOpen = None
108108
eosEvmMinerPOpen = None
109109

110+
def assert_contract_exist(contract_addr):
111+
Utils.Print("ensure contract {0} exist".format(contract_addr))
112+
if contract_addr[:2] == '0x':
113+
contract_addr = contract_addr[2:]
114+
rows=prodNode.getTable(evmAcc.name, evmAcc.name, "account")
115+
for row in rows['rows']:
116+
if (str(contract_addr) == str(row['eth_address'])):
117+
assert row['code_id'] is not None, "contract {0} should exist".format(contract_addr)
118+
return True
119+
Utils.Print("evm account table rows: " + json.dumps(rows))
120+
assert False, "contract {0} should exist".format(contract_addr)
121+
110122
def interact_with_storage_contract(dest, nonce):
111123
for i in range(1, 5): # execute a few
112124
Utils.Print("Execute ETH contract")
@@ -291,7 +303,7 @@ def toDict(dictToParse):
291303
prodNode = cluster.getNode(0)
292304
nonProdNode = cluster.getNode(1)
293305

294-
accounts=createAccountKeys(6)
306+
accounts=createAccountKeys(7)
295307
if accounts is None:
296308
Utils.errorExit("FAILURE - create keys")
297309

@@ -303,10 +315,13 @@ def toDict(dictToParse):
303315
defertest2Acc = accounts[4]
304316
aliceAcc = accounts[5]
305317

318+
accounts[6].name = "evmbridge"
319+
evmbridgeAcc = accounts[6]
320+
306321
testWalletName="test"
307322

308323
Print("Creating wallet \"%s\"." % (testWalletName))
309-
testWallet=walletMgr.create(testWalletName, [cluster.eosioAccount,accounts[0],accounts[1],accounts[2],accounts[3],accounts[4]])
324+
testWallet=walletMgr.create(testWalletName, [cluster.eosioAccount,accounts[0],accounts[1],accounts[2],accounts[3],accounts[4],accounts[5],accounts[6]])
310325

311326
addys = {
312327
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266":"0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75,0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
@@ -356,6 +371,15 @@ def toDict(dictToParse):
356371
Utils.Print(f"Publish defertest2 contract {contractDir}/{wasmFile} to account {defertest2Acc}")
357372
prodNode.publishContract(defertest2Acc, contractDir, wasmFile, abiFile, waitForTransBlock=True)
358373

374+
contractDir=eosEvmBuildRoot + "/tests"
375+
wasmFile="evmbridge.wasm"
376+
abiFile="evmbridge.abi"
377+
Utils.Print(f"Publish evmbridge contract {contractDir}/{wasmFile} to account {evmbridgeAcc}")
378+
prodNode.publishContract(evmbridgeAcc, contractDir, wasmFile, abiFile, waitForTransBlock=True)
379+
# add eosio.code evmbridge
380+
cmd="set account permission evmbridge active --add-code -p evmbridge@active"
381+
prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw)
382+
359383
# add eosio.code permission to defertest2 account
360384
cmd="set account permission " + defertest2Acc.name + " active --add-code -p " + defertest2Acc.name + "@active"
361385
prodNode.processCleosCmd(cmd, cmd, silentErrors=False, returnType=ReturnType.raw)
@@ -527,6 +551,7 @@ def toDict(dictToParse):
527551
actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(get_raw_transaction(signed_trx))[2:]}
528552
retValue = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True)
529553
assert retValue[0], f"push trx should have succeeded: {retValue}"
554+
assert_contract_exist(makeContractAddress(fromAdd, nonce))
530555
nonce = interact_with_storage_contract(makeContractAddress(fromAdd, nonce), nonce)
531556

532557
if genesisJson[0] != '/': genesisJson = os.path.realpath(genesisJson)
@@ -820,6 +845,7 @@ def toDict(dictToParse):
820845

821846

822847
# Launch eos-evm-node
848+
Utils.Print("===== laucnhing eos-evm-node & eos-evm-rpc =====")
823849
dataDir = Utils.DataDir + "eos_evm"
824850
nodeStdOutDir = dataDir + "/eos-evm-node.stdout"
825851
nodeStdErrDir = dataDir + "/eos-evm-node.stderr"
@@ -901,6 +927,69 @@ def get_block(num):
901927
nonProdNode.transferFunds(cluster.eosioAccount, evmAcc, "111.0000 EOS", "0xB106D2C286183FFC3D1F0C4A6f0753bB20B407c2", waitForTransBlock=True)
902928
time.sleep(2)
903929

930+
### evmtx event order test
931+
Utils.Print("Test evmtx event order via evmbridge contract")
932+
# // SPDX-License-Identifier: GPL-3.0
933+
# pragma solidity >=0.7.0 <0.9.0;
934+
# contract BridgeTest {
935+
# uint256 number;
936+
# constructor() {
937+
# number = 41;
938+
# }
939+
# function assertdata(uint256 expect) payable public {
940+
# require(number == expect, "assertdata failed");
941+
# number = number + 1;
942+
# }
943+
# function sendbridgemsg() payable public {
944+
# number = number + 1;
945+
# bytes memory receiver_msg = abi.encodeWithSignature("test(uint256)", number);
946+
# address evmaddr = 0xbBBBbBbbbBBBBbbbbbbBBbBB5530EA015b900000;//eosio.evm
947+
# (bool success, ) = evmaddr.call{value: msg.value}(
948+
# abi.encodeWithSignature("bridgeMsgV0(string,bool,bytes)", "evmbridge", true, receiver_msg ));
949+
# if(!success) { revert(); }
950+
# }
951+
# }
952+
#
953+
nonce += 1
954+
evmChainId = 15555
955+
gasP = getGasPrice()
956+
signed_trx = w3.eth.account.sign_transaction(dict(
957+
nonce=nonce,
958+
gas=5000000,
959+
gasPrice=gasP,
960+
data=Web3.to_bytes(hexstr='608060405234801561001057600080fd5b5060296000819055506105b2806100286000396000f3fe6080604052600436106100285760003560e01c80628fcf3e1461002d57806386bf4eff14610049575b600080fd5b610047600480360381019061004291906102b8565b610053565b005b6100516100af565b005b8060005414610097576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161008e90610342565b60405180910390fd5b60016000546100a69190610391565b60008190555050565b60016000546100be9190610391565b600081905550600080546040516024016100d891906103d4565b6040516020818303038152906040527f29e99f07000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600073bbbbbbbbbbbbbbbbbbbbbbbb5530ea015b900000905060008173ffffffffffffffffffffffffffffffffffffffff163460018560405160240161019e9291906104e6565b6040516020818303038152906040527ff781185b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516102289190610565565b60006040518083038185875af1925050503d8060008114610265576040519150601f19603f3d011682016040523d82523d6000602084013e61026a565b606091505b505090508061027857600080fd5b505050565b600080fd5b6000819050919050565b61029581610282565b81146102a057600080fd5b50565b6000813590506102b28161028c565b92915050565b6000602082840312156102ce576102cd61027d565b5b60006102dc848285016102a3565b91505092915050565b600082825260208201905092915050565b7f61737365727464617461206661696c6564000000000000000000000000000000600082015250565b600061032c6011836102e5565b9150610337826102f6565b602082019050919050565b6000602082019050818103600083015261035b8161031f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061039c82610282565b91506103a783610282565b92508282019050808211156103bf576103be610362565b5b92915050565b6103ce81610282565b82525050565b60006020820190506103e960008301846103c5565b92915050565b7f65766d6272696467650000000000000000000000000000000000000000000000600082015250565b60006104256009836102e5565b9150610430826103ef565b602082019050919050565b60008115159050919050565b6104508161043b565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610490578082015181840152602081019050610475565b60008484015250505050565b6000601f19601f8301169050919050565b60006104b882610456565b6104c28185610461565b93506104d2818560208601610472565b6104db8161049c565b840191505092915050565b600060608201905081810360008301526104ff81610418565b905061050e6020830185610447565b818103604083015261052081846104ad565b90509392505050565b600081905092915050565b600061053f82610456565b6105498185610529565b9350610559818560208601610472565b80840191505092915050565b60006105718284610534565b91508190509291505056fea2646970667358221220ac18e6f72606f415174ea5fa2cf02da58e2ec7af6b59282e166efa50f79aef3164736f6c63430008120033'),
961+
chainId=evmChainId
962+
), evmSendKey)
963+
actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(get_raw_transaction(signed_trx))[2:]}
964+
retValue = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True)
965+
assert retValue[0], f"push trx should have succeeded: {retValue}"
966+
bridgemsgcontractaddr = makeContractAddress("9E126C57330FA71556628e0aabd6B6B6783d99fA", nonce)
967+
assert_contract_exist(bridgemsgcontractaddr)
968+
Utils.Print("bridge msg contract addr is:" + str(bridgemsgcontractaddr))
969+
row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test
970+
Utils.Print("\taccount row4: ", row4)
971+
972+
Utils.Print("call bridgereg in evm runtime contract for account evmbridge")
973+
prodNode.pushMessage(evmAcc.name, "bridgereg", '["evmbridge","evmbridge","1.0000 EOS"]', '-p {0} -p evmbridge'.format(evmAcc.name), silentErrors=False)
974+
975+
Utils.Print("push EVM trx to trigger bridgemsg from EVM to notify evmbridge account")
976+
amount=1.0000
977+
nonce += 1
978+
signed_trx = w3.eth.account.sign_transaction(dict(
979+
nonce=nonce,
980+
gas=100000,
981+
gasPrice=gasP,
982+
to=Web3.to_checksum_address(bridgemsgcontractaddr),
983+
data=Web3.to_bytes(hexstr='86bf4eff'), #function sendbridgemsg()
984+
value=int(amount*10000*szabo*100),
985+
chainId=evmChainId
986+
), evmSendKey)
987+
actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(get_raw_transaction(signed_trx))[2:]}
988+
retValue = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=False)
989+
assert retValue[0], f"push trx to bridge msg contract should have succeeded: {retValue}"
990+
row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test
991+
Utils.Print("\taccount row4: ", row4)
992+
904993
# update gas parameter
905994
Utils.Print("Update gas parameter: ram price = 100 EOS per MB, gas price = 900Gwei")
906995
trans = prodNode.pushMessage(evmAcc.name, "updtgasparam", json.dumps({"ram_price_mb":"100.0000 EOS","gas_price":900000000000}), '-p {0}'.format(evmAcc.name), silentErrors=False)
@@ -1107,6 +1196,62 @@ def get_block(num):
11071196
# Validate all balances (check evmtx event)
11081197
validate_all_balances()
11091198

1199+
####### BEGIN Test eth_getLogs
1200+
# // SPDX-License-Identifier: GPL-3.0
1201+
# pragma solidity >=0.7.0 <0.9.0;
1202+
# contract Eventor {
1203+
# event Deposit(address indexed _from, uint _value);
1204+
# function deposit(uint256 _value) public {
1205+
# emit Deposit(msg.sender, _value);
1206+
# }
1207+
# }
1208+
1209+
Print("Test eth_getLogs (deploy contract)")
1210+
special_nonce += 1
1211+
signed_trx = w3.eth.account.sign_transaction(dict(
1212+
nonce=special_nonce,
1213+
gas=2000000,
1214+
maxFeePerGas = 900000000000,
1215+
maxPriorityFeePerGas = 900000000000,
1216+
data=Web3.to_bytes(hexstr='608060405234801561001057600080fd5b50610165806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b6b55f2514610030575b600080fd5b61004a600480360381019061004591906100d8565b61004c565b005b3373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c826040516100929190610114565b60405180910390a250565b600080fd5b6000819050919050565b6100b5816100a2565b81146100c057600080fd5b50565b6000813590506100d2816100ac565b92915050565b6000602082840312156100ee576100ed61009d565b5b60006100fc848285016100c3565b91505092915050565b61010e816100a2565b82525050565b60006020820190506101296000830184610105565b9291505056fea26469706673582212204e317ada7494f9d6291c2dc3071bb4892e3018729f4b94e5e6aa88bbf8224c3864736f6c634300080d0033'),
1217+
chainId=15555
1218+
), accSpecialKey)
1219+
1220+
# Deploy "Eventor" contract
1221+
eventor_contract = makeContractAddress(accSpecialAdd, special_nonce)
1222+
actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(get_raw_transaction(signed_trx))[2:]}
1223+
trans = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True)
1224+
prodNode.waitForTransBlockIfNeeded(trans[1], True);
1225+
time.sleep(2)
1226+
1227+
Print("Test eth_getLogs (call deposit)")
1228+
special_nonce += 1
1229+
signed_trx = w3.eth.account.sign_transaction(dict(
1230+
nonce=special_nonce,
1231+
gas=2000000,
1232+
maxFeePerGas = 900000000000,
1233+
maxPriorityFeePerGas = 900000000000,
1234+
to=Web3.to_checksum_address(eventor_contract),
1235+
data=Web3.to_bytes(hexstr='b6b55f250000000000000000000000000000000000000000000000000000000000000016'),
1236+
chainId=15555
1237+
), accSpecialKey)
1238+
1239+
actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(get_raw_transaction(signed_trx))[2:]}
1240+
trans = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True)
1241+
prodNode.waitForTransBlockIfNeeded(trans[1], True);
1242+
time.sleep(4)
1243+
1244+
deposit_tx = w3.eth.get_transaction_receipt(signed_trx.hash)
1245+
logs = w3.eth.get_logs({
1246+
'fromBlock': deposit_tx['blockNumber'],
1247+
'toBlock': deposit_tx['blockNumber']
1248+
})
1249+
1250+
assert(len(logs) == 1)
1251+
assert(str(logs[0]['address']).lower() == str(eventor_contract).lower())
1252+
1253+
####### END Test eth_getLogs
1254+
11101255
Utils.Print("checking %s for errors" % (nodeStdErrDir))
11111256
foundErr = False
11121257
stdErrFile = open(nodeStdErrDir, "r")

0 commit comments

Comments
 (0)