From 967c5494a92fc1bfe76291afe3e6729820b89d30 Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:31:22 +0900 Subject: [PATCH] fix revert error to return proper error message (#103) --- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- x/evm/contracts/counter/Counter.go | 2 +- x/evm/contracts/counter/Counter.sol | 2 +- x/evm/keeper/context.go | 21 +++--- x/evm/keeper/context_test.go | 5 +- x/evm/keeper/keeper.go | 12 ---- x/evm/keeper/precompiles.go | 39 ++++------- x/evm/keeper/precompiles_test.go | 48 +++++++++++++ x/evm/precompiles/cosmos/contract.go | 33 +++++---- x/evm/precompiles/cosmos/contract_test.go | 67 ++++++++----------- x/evm/precompiles/erc20_registry/contract.go | 31 +++++---- .../erc20_registry/contract_test.go | 7 +- x/evm/types/errors.go | 36 ++++++++-- x/evm/types/expected_keeper.go | 4 -- 17 files changed, 185 insertions(+), 134 deletions(-) diff --git a/go.mod b/go.mod index 7830b3c..719cff2 100644 --- a/go.mod +++ b/go.mod @@ -288,7 +288,7 @@ replace ( replace ( github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261 github.com/cosmos/ibc-go/v8 => github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d - github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98 + github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb // use custom version until this PR is merged // - https://github.com/strangelove-ventures/cometbft-client/pull/10 diff --git a/go.sum b/go.sum index 447fba6..c3b9769 100644 --- a/go.sum +++ b/go.sum @@ -1440,8 +1440,8 @@ github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261 h1:V62KOhe6Em github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261/go.mod h1:KsQ7Wm/dw9N0l7Ypn3QKGwgUX5XinTlcHGIF0DSjsw4= github.com/initia-labs/cometbft-client v0.0.0-20240924071428-ef115cefa07e h1:k+pg63SFozCAK4LZFSiZtof6z69Tlu0O/Zftj1aAwes= github.com/initia-labs/cometbft-client v0.0.0-20240924071428-ef115cefa07e/go.mod h1:aVposiPW9FOUeAeJ7JjJRdE3g+L6i8YDxFn6Cv6+Az4= -github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98 h1:JmJpxtYnF++Lj9MhD2LxOtgNAJM0aYqgO9nBkuhiGlI= -github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= +github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb h1:oyH9gg/4f7uMCIJYnSpp7wa1NrGjSMsXTtypUfrsPLU= +github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d h1:TLq8lB1PtQ0pjGf+bN8YgGVeLMuytZ26SBGMOs1seKY= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= github.com/initia-labs/initia v0.6.0 h1:/39ZN26zeixxZZdcfY1sOitiBhfnG3lcbPtpFqd9z7A= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 79d24a5..37b69cf 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -271,7 +271,7 @@ replace ( replace ( github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261 github.com/cosmos/ibc-go/v8 => github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d - github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98 + github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb // use custom version until this PR is merged // - https://github.com/strangelove-ventures/cometbft-client/pull/10 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index fafc6d6..4249741 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1398,8 +1398,8 @@ github.com/initia-labs/OPinit/api v0.5.1 h1:zwyJf7HtKJCKvLJ1R9PjVfJO1L+d/jKoeFyT github.com/initia-labs/OPinit/api v0.5.1/go.mod h1:gHK6DEWb3/DqQD5LjKirUx9jilAh2UioXanoQdgqVfU= github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261 h1:V62KOhe6Em3wAvJsDVP+3is98I3mk/29OKNVs4IxeFQ= github.com/initia-labs/cometbft v0.0.0-20240925132752-ff8ff0126261/go.mod h1:KsQ7Wm/dw9N0l7Ypn3QKGwgUX5XinTlcHGIF0DSjsw4= -github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98 h1:JmJpxtYnF++Lj9MhD2LxOtgNAJM0aYqgO9nBkuhiGlI= -github.com/initia-labs/evm v0.0.0-20241105070652-c43b570a4e98/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= +github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb h1:oyH9gg/4f7uMCIJYnSpp7wa1NrGjSMsXTtypUfrsPLU= +github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d h1:TLq8lB1PtQ0pjGf+bN8YgGVeLMuytZ26SBGMOs1seKY= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= github.com/initia-labs/initia v0.6.0 h1:/39ZN26zeixxZZdcfY1sOitiBhfnG3lcbPtpFqd9z7A= diff --git a/x/evm/contracts/counter/Counter.go b/x/evm/contracts/counter/Counter.go index 4aa8d93..54643b6 100644 --- a/x/evm/contracts/counter/Counter.go +++ b/x/evm/contracts/counter/Counter.go @@ -32,7 +32,7 @@ var ( // CounterMetaData contains all meta data concerning the Counter contract. var CounterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"StringsInsufficientHexLength\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"callback_received\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCount\",\"type\":\"uint256\"}],\"name\":\"increased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"n\",\"type\":\"uint64\"}],\"name\":\"recursive_called\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"callback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"exec_msg\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"call_revert\",\"type\":\"bool\"}],\"name\":\"execute_cosmos\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"exec_msg\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"allow_failure\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"}],\"name\":\"execute_cosmos_with_options\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"n\",\"type\":\"uint64\"}],\"name\":\"get_blockhash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"ibc_ack\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"}],\"name\":\"ibc_timeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"increase\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"path\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"req\",\"type\":\"string\"}],\"name\":\"query_cosmos\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"result\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"n\",\"type\":\"uint64\"}],\"name\":\"recursive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052611945806100115f395ff3fe608060405260043610610090575f3560e01c80637876da75116100585780637876da751461015e578063ac7fde5f14610186578063c31925a7146101c2578063cad23554146101ea578063e8927fbc1461022657610090565b806306661abd146100945780630d4f1f9d146100be57806324c68fce146100e657806331a503f01461010e5780636193689514610136575b5f80fd5b34801561009f575f80fd5b506100a8610230565b6040516100b59190610ca1565b60405180910390f35b3480156100c9575f80fd5b506100e460048036038101906100df9190610d3d565b610235565b005b3480156100f1575f80fd5b5061010c60048036038101906101079190610eb7565b61027c565b005b348015610119575f80fd5b50610134600480360381019061012f9190610f11565b61033c565b005b348015610141575f80fd5b5061015c60048036038101906101579190610f11565b610360565b005b348015610169575f80fd5b50610184600480360381019061017f9190610f3c565b6104b3565b005b348015610191575f80fd5b506101ac60048036038101906101a79190610f11565b610555565b6040516101b99190610fc0565b60405180910390f35b3480156101cd575f80fd5b506101e860048036038101906101e39190610d3d565b610569565b005b3480156101f5575f80fd5b50610210600480360381019061020b9190610fd9565b6105a6565b60405161021d91906110af565b60405180910390f35b61022e61062f565b005b5f5481565b8015610261578167ffffffffffffffff165f8082825461025591906110fc565b92505081905550610278565b5f808154809291906102729061112f565b91905055505b5050565b60f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e6836040518263ffffffff1660e01b81526004016102b691906110af565b6020604051808303815f875af11580156102d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f6919061118a565b508015610338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032f906111ff565b60405180910390fd5b5050565b8067ffffffffffffffff165f8082825461035691906110fc565b9250508190555050565b7f4475bbd12ef452e28d39c4cb77494d85136c2d89ca1354b52188d4aaa8f4ba518160405161038f919061122c565b60405180910390a15f8167ffffffffffffffff1603156104b05760f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66103cf8361068e565b6040518263ffffffff1660e01b81526004016103eb91906110af565b6020604051808303815f875af1158015610407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042b919061118a565b5060f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66104528361068e565b6040518263ffffffff1660e01b815260040161046e91906110af565b6020604051808303815f875af115801561048a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ae919061118a565b505b50565b60f173ffffffffffffffffffffffffffffffffffffffff16636c4f6bd584604051806040016040528086151581526020018567ffffffffffffffff168152506040518363ffffffff1660e01b815260040161050f929190611290565b6020604051808303815f875af115801561052b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061054f919061118a565b50505050565b5f8167ffffffffffffffff16409050919050565b7fa019c7431cdfd7ba63501ffa1ba7d8f2a028e447653a5af5a96077e5038e0339828260405161059a9291906112cd565b60405180910390a15050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b81526004016105e49291906112f4565b5f604051808303815f875af11580156105ff573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906106279190611397565b905092915050565b5f808154809291906106409061112f565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f5461067491906113de565b5f54604051610684929190611411565b60405180910390a1565b606060f173ffffffffffffffffffffffffffffffffffffffff16636af32a55306040518263ffffffff1660e01b81526004016106ca9190611477565b5f604051808303815f875af11580156106e5573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061070d9190611397565b6107163061079a565b610772636193689560e01b60018661072e9190611490565b60405160200161073e919061122c565b60405160208183030381529060405260405160200161075e92919061155a565b6040516020818303038152906040526107c7565b604051602001610784939291906117e7565b6040516020818303038152906040529050919050565b60606107c08273ffffffffffffffffffffffffffffffffffffffff16601460ff16610a4b565b9050919050565b60605f60028084516107d9919061187a565b6107e391906110fc565b67ffffffffffffffff8111156107fc576107fb610d93565b5b6040519080825280601f01601f19166020018201604052801561082e5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f81518110610865576108646118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106108c8576108c76118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f5b8351811015610a41575f848281518110610915576109146118bb565b5b602001015160f81c60f81b60f81c90507f303132333435363738396162636465660000000000000000000000000000000060048260ff16901c60ff1660108110610962576109616118bb565b5b1a60f81b836002808502018151811061097e5761097d6118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f3031323334353637383961626364656600000000000000000000000000000000600f821660ff16601081106109e5576109e46118bb565b5b1a60f81b836002600160028602010181518110610a0557610a046118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505080806001019150506108f8565b5080915050919050565b60605f8390505f6002846002610a61919061187a565b610a6b91906110fc565b67ffffffffffffffff811115610a8457610a83610d93565b5b6040519080825280601f01601f191660200182016040528015610ab65781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f81518110610aed57610aec6118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610b5057610b4f6118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f6001856002610b8e919061187a565b610b9891906110fc565b90505b6001811115610c37577f3031323334353637383961626364656600000000000000000000000000000000600f841660108110610bda57610bd96118bb565b5b1a60f81b828281518110610bf157610bf06118bb565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c925080610c30906118e8565b9050610b9b565b505f8214610c7e5784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401610c75929190611411565b60405180910390fd5b809250505092915050565b5f819050919050565b610c9b81610c89565b82525050565b5f602082019050610cb45f830184610c92565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b610ce781610ccb565b8114610cf1575f80fd5b50565b5f81359050610d0281610cde565b92915050565b5f8115159050919050565b610d1c81610d08565b8114610d26575f80fd5b50565b5f81359050610d3781610d13565b92915050565b5f8060408385031215610d5357610d52610cc3565b5b5f610d6085828601610cf4565b9250506020610d7185828601610d29565b9150509250929050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610dc982610d83565b810181811067ffffffffffffffff82111715610de857610de7610d93565b5b80604052505050565b5f610dfa610cba565b9050610e068282610dc0565b919050565b5f67ffffffffffffffff821115610e2557610e24610d93565b5b610e2e82610d83565b9050602081019050919050565b828183375f83830152505050565b5f610e5b610e5684610e0b565b610df1565b905082815260208101848484011115610e7757610e76610d7f565b5b610e82848285610e3b565b509392505050565b5f82601f830112610e9e57610e9d610d7b565b5b8135610eae848260208601610e49565b91505092915050565b5f8060408385031215610ecd57610ecc610cc3565b5b5f83013567ffffffffffffffff811115610eea57610ee9610cc7565b5b610ef685828601610e8a565b9250506020610f0785828601610d29565b9150509250929050565b5f60208284031215610f2657610f25610cc3565b5b5f610f3384828501610cf4565b91505092915050565b5f805f60608486031215610f5357610f52610cc3565b5b5f84013567ffffffffffffffff811115610f7057610f6f610cc7565b5b610f7c86828701610e8a565b9350506020610f8d86828701610d29565b9250506040610f9e86828701610cf4565b9150509250925092565b5f819050919050565b610fba81610fa8565b82525050565b5f602082019050610fd35f830184610fb1565b92915050565b5f8060408385031215610fef57610fee610cc3565b5b5f83013567ffffffffffffffff81111561100c5761100b610cc7565b5b61101885828601610e8a565b925050602083013567ffffffffffffffff81111561103957611038610cc7565b5b61104585828601610e8a565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f6110818261104f565b61108b8185611059565b935061109b818560208601611069565b6110a481610d83565b840191505092915050565b5f6020820190508181035f8301526110c78184611077565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61110682610c89565b915061111183610c89565b9250828201905080821115611129576111286110cf565b5b92915050565b5f61113982610c89565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361116b5761116a6110cf565b5b600182019050919050565b5f8151905061118481610d13565b92915050565b5f6020828403121561119f5761119e610cc3565b5b5f6111ac84828501611176565b91505092915050565b7f72657665727400000000000000000000000000000000000000000000000000005f82015250565b5f6111e9600683611059565b91506111f4826111b5565b602082019050919050565b5f6020820190508181035f830152611216816111dd565b9050919050565b61122681610ccb565b82525050565b5f60208201905061123f5f83018461121d565b92915050565b61124e81610d08565b82525050565b61125d81610ccb565b82525050565b604082015f8201516112775f850182611245565b50602082015161128a6020850182611254565b50505050565b5f6060820190508181035f8301526112a88185611077565b90506112b76020830184611263565b9392505050565b6112c781610d08565b82525050565b5f6040820190506112e05f83018561121d565b6112ed60208301846112be565b9392505050565b5f6040820190508181035f83015261130c8185611077565b905081810360208301526113208184611077565b90509392505050565b5f61133b61133684610e0b565b610df1565b90508281526020810184848401111561135757611356610d7f565b5b611362848285611069565b509392505050565b5f82601f83011261137e5761137d610d7b565b5b815161138e848260208601611329565b91505092915050565b5f602082840312156113ac576113ab610cc3565b5b5f82015167ffffffffffffffff8111156113c9576113c8610cc7565b5b6113d58482850161136a565b91505092915050565b5f6113e882610c89565b91506113f383610c89565b925082820390508181111561140b5761140a6110cf565b5b92915050565b5f6040820190506114245f830185610c92565b6114316020830184610c92565b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61146182611438565b9050919050565b61147181611457565b82525050565b5f60208201905061148a5f830184611468565b92915050565b5f61149a82610ccb565b91506114a583610ccb565b9250828203905067ffffffffffffffff8111156114c5576114c46110cf565b5b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b5f819050919050565b61151061150b826114cb565b6114f6565b82525050565b5f81519050919050565b5f81905092915050565b5f61153482611516565b61153e8185611520565b935061154e818560208601611069565b80840191505092915050565b5f61156582856114ff565b600482019150611575828461152a565b91508190509392505050565b5f81905092915050565b7f7b224074797065223a20222f6d696e6965766d2e65766d2e76312e4d736743615f8201527f6c6c222c00000000000000000000000000000000000000000000000000000000602082015250565b5f6115e5602483611581565b91506115f08261158b565b602482019050919050565b7f2273656e646572223a20220000000000000000000000000000000000000000005f82015250565b5f61162f600b83611581565b915061163a826115fb565b600b82019050919050565b5f61164f8261104f565b6116598185611581565b9350611669818560208601611069565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6116a9600283611581565b91506116b482611675565b600282019050919050565b7f22636f6e74726163745f61646472223a202200000000000000000000000000005f82015250565b5f6116f3601283611581565b91506116fe826116bf565b601282019050919050565b7f22696e707574223a2022000000000000000000000000000000000000000000005f82015250565b5f61173d600a83611581565b915061174882611709565b600a82019050919050565b7f2276616c7565223a202230222c000000000000000000000000000000000000005f82015250565b5f611787600d83611581565b915061179282611753565b600d82019050919050565b7f226163636573735f6c697374223a205b5d7d00000000000000000000000000005f82015250565b5f6117d1601283611581565b91506117dc8261179d565b601282019050919050565b5f6117f1826115d9565b91506117fc82611623565b91506118088286611645565b91506118138261169d565b915061181e826116e7565b915061182a8285611645565b91506118358261169d565b915061184082611731565b915061184c8284611645565b91506118578261169d565b91506118628261177b565b915061186d826117c5565b9150819050949350505050565b5f61188482610c89565b915061188f83610c89565b925082820261189d81610c89565b915082820484148315176118b4576118b36110cf565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6118f282610c89565b91505f8203611904576119036110cf565b5b60018203905091905056fea2646970667358221220339661d4205cce53f87640e4bda7b986420a18209cdc6fdfb167bafc740fc9fe64736f6c63430008190033", + Bin: "0x608060405261196b806100115f395ff3fe608060405260043610610090575f3560e01c80637876da75116100585780637876da751461015e578063ac7fde5f14610186578063c31925a7146101c2578063cad23554146101ea578063e8927fbc1461022657610090565b806306661abd146100945780630d4f1f9d146100be57806324c68fce146100e657806331a503f01461010e5780636193689514610136575b5f80fd5b34801561009f575f80fd5b506100a8610230565b6040516100b59190610ca1565b60405180910390f35b3480156100c9575f80fd5b506100e460048036038101906100df9190610d3d565b610235565b005b3480156100f1575f80fd5b5061010c60048036038101906101079190610eb7565b61027c565b005b348015610119575f80fd5b50610134600480360381019061012f9190610f11565b61033c565b005b348015610141575f80fd5b5061015c60048036038101906101579190610f11565b610360565b005b348015610169575f80fd5b50610184600480360381019061017f9190610f3c565b6104b3565b005b348015610191575f80fd5b506101ac60048036038101906101a79190610f11565b610555565b6040516101b99190610fc0565b60405180910390f35b3480156101cd575f80fd5b506101e860048036038101906101e39190610d3d565b610569565b005b3480156101f5575f80fd5b50610210600480360381019061020b9190610fd9565b6105a6565b60405161021d91906110af565b60405180910390f35b61022e61062f565b005b5f5481565b8015610261578167ffffffffffffffff165f8082825461025591906110fc565b92505081905550610278565b5f808154809291906102729061112f565b91905055505b5050565b60f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e6836040518263ffffffff1660e01b81526004016102b691906110af565b6020604051808303815f875af11580156102d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f6919061118a565b508015610338576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032f90611225565b60405180910390fd5b5050565b8067ffffffffffffffff165f8082825461035691906110fc565b9250508190555050565b7f4475bbd12ef452e28d39c4cb77494d85136c2d89ca1354b52188d4aaa8f4ba518160405161038f9190611252565b60405180910390a15f8167ffffffffffffffff1603156104b05760f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66103cf8361068e565b6040518263ffffffff1660e01b81526004016103eb91906110af565b6020604051808303815f875af1158015610407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042b919061118a565b5060f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66104528361068e565b6040518263ffffffff1660e01b815260040161046e91906110af565b6020604051808303815f875af115801561048a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ae919061118a565b505b50565b60f173ffffffffffffffffffffffffffffffffffffffff16636c4f6bd584604051806040016040528086151581526020018567ffffffffffffffff168152506040518363ffffffff1660e01b815260040161050f9291906112b6565b6020604051808303815f875af115801561052b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061054f919061118a565b50505050565b5f8167ffffffffffffffff16409050919050565b7fa019c7431cdfd7ba63501ffa1ba7d8f2a028e447653a5af5a96077e5038e0339828260405161059a9291906112f3565b60405180910390a15050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b81526004016105e492919061131a565b5f604051808303815f875af11580156105ff573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061062791906113bd565b905092915050565b5f808154809291906106409061112f565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f546106749190611404565b5f54604051610684929190611437565b60405180910390a1565b606060f173ffffffffffffffffffffffffffffffffffffffff16636af32a55306040518263ffffffff1660e01b81526004016106ca919061149d565b5f604051808303815f875af11580156106e5573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061070d91906113bd565b6107163061079a565b610772636193689560e01b60018661072e91906114b6565b60405160200161073e9190611252565b60405160208183030381529060405260405160200161075e929190611580565b6040516020818303038152906040526107c7565b6040516020016107849392919061180d565b6040516020818303038152906040529050919050565b60606107c08273ffffffffffffffffffffffffffffffffffffffff16601460ff16610a4b565b9050919050565b60605f60028084516107d991906118a0565b6107e391906110fc565b67ffffffffffffffff8111156107fc576107fb610d93565b5b6040519080825280601f01601f19166020018201604052801561082e5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f81518110610865576108646118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106108c8576108c76118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f5b8351811015610a41575f848281518110610915576109146118e1565b5b602001015160f81c60f81b60f81c90507f303132333435363738396162636465660000000000000000000000000000000060048260ff16901c60ff1660108110610962576109616118e1565b5b1a60f81b836002808502018151811061097e5761097d6118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f3031323334353637383961626364656600000000000000000000000000000000600f821660ff16601081106109e5576109e46118e1565b5b1a60f81b836002600160028602010181518110610a0557610a046118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505080806001019150506108f8565b5080915050919050565b60605f8390505f6002846002610a6191906118a0565b610a6b91906110fc565b67ffffffffffffffff811115610a8457610a83610d93565b5b6040519080825280601f01601f191660200182016040528015610ab65781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f81518110610aed57610aec6118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110610b5057610b4f6118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f6001856002610b8e91906118a0565b610b9891906110fc565b90505b6001811115610c37577f3031323334353637383961626364656600000000000000000000000000000000600f841660108110610bda57610bd96118e1565b5b1a60f81b828281518110610bf157610bf06118e1565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c925080610c309061190e565b9050610b9b565b505f8214610c7e5784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401610c75929190611437565b60405180910390fd5b809250505092915050565b5f819050919050565b610c9b81610c89565b82525050565b5f602082019050610cb45f830184610c92565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b610ce781610ccb565b8114610cf1575f80fd5b50565b5f81359050610d0281610cde565b92915050565b5f8115159050919050565b610d1c81610d08565b8114610d26575f80fd5b50565b5f81359050610d3781610d13565b92915050565b5f8060408385031215610d5357610d52610cc3565b5b5f610d6085828601610cf4565b9250506020610d7185828601610d29565b9150509250929050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610dc982610d83565b810181811067ffffffffffffffff82111715610de857610de7610d93565b5b80604052505050565b5f610dfa610cba565b9050610e068282610dc0565b919050565b5f67ffffffffffffffff821115610e2557610e24610d93565b5b610e2e82610d83565b9050602081019050919050565b828183375f83830152505050565b5f610e5b610e5684610e0b565b610df1565b905082815260208101848484011115610e7757610e76610d7f565b5b610e82848285610e3b565b509392505050565b5f82601f830112610e9e57610e9d610d7b565b5b8135610eae848260208601610e49565b91505092915050565b5f8060408385031215610ecd57610ecc610cc3565b5b5f83013567ffffffffffffffff811115610eea57610ee9610cc7565b5b610ef685828601610e8a565b9250506020610f0785828601610d29565b9150509250929050565b5f60208284031215610f2657610f25610cc3565b5b5f610f3384828501610cf4565b91505092915050565b5f805f60608486031215610f5357610f52610cc3565b5b5f84013567ffffffffffffffff811115610f7057610f6f610cc7565b5b610f7c86828701610e8a565b9350506020610f8d86828701610d29565b9250506040610f9e86828701610cf4565b9150509250925092565b5f819050919050565b610fba81610fa8565b82525050565b5f602082019050610fd35f830184610fb1565b92915050565b5f8060408385031215610fef57610fee610cc3565b5b5f83013567ffffffffffffffff81111561100c5761100b610cc7565b5b61101885828601610e8a565b925050602083013567ffffffffffffffff81111561103957611038610cc7565b5b61104585828601610e8a565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f6110818261104f565b61108b8185611059565b935061109b818560208601611069565b6110a481610d83565b840191505092915050565b5f6020820190508181035f8301526110c78184611077565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61110682610c89565b915061111183610c89565b9250828201905080821115611129576111286110cf565b5b92915050565b5f61113982610c89565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361116b5761116a6110cf565b5b600182019050919050565b5f8151905061118481610d13565b92915050565b5f6020828403121561119f5761119e610cc3565b5b5f6111ac84828501611176565b91505092915050565b7f72657665727420726561736f6e2064756d6d792076616c756520666f722074655f8201527f7374000000000000000000000000000000000000000000000000000000000000602082015250565b5f61120f602283611059565b915061121a826111b5565b604082019050919050565b5f6020820190508181035f83015261123c81611203565b9050919050565b61124c81610ccb565b82525050565b5f6020820190506112655f830184611243565b92915050565b61127481610d08565b82525050565b61128381610ccb565b82525050565b604082015f82015161129d5f85018261126b565b5060208201516112b0602085018261127a565b50505050565b5f6060820190508181035f8301526112ce8185611077565b90506112dd6020830184611289565b9392505050565b6112ed81610d08565b82525050565b5f6040820190506113065f830185611243565b61131360208301846112e4565b9392505050565b5f6040820190508181035f8301526113328185611077565b905081810360208301526113468184611077565b90509392505050565b5f61136161135c84610e0b565b610df1565b90508281526020810184848401111561137d5761137c610d7f565b5b611388848285611069565b509392505050565b5f82601f8301126113a4576113a3610d7b565b5b81516113b484826020860161134f565b91505092915050565b5f602082840312156113d2576113d1610cc3565b5b5f82015167ffffffffffffffff8111156113ef576113ee610cc7565b5b6113fb84828501611390565b91505092915050565b5f61140e82610c89565b915061141983610c89565b9250828203905081811115611431576114306110cf565b5b92915050565b5f60408201905061144a5f830185610c92565b6114576020830184610c92565b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6114878261145e565b9050919050565b6114978161147d565b82525050565b5f6020820190506114b05f83018461148e565b92915050565b5f6114c082610ccb565b91506114cb83610ccb565b9250828203905067ffffffffffffffff8111156114eb576114ea6110cf565b5b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b5f819050919050565b611536611531826114f1565b61151c565b82525050565b5f81519050919050565b5f81905092915050565b5f61155a8261153c565b6115648185611546565b9350611574818560208601611069565b80840191505092915050565b5f61158b8285611525565b60048201915061159b8284611550565b91508190509392505050565b5f81905092915050565b7f7b224074797065223a20222f6d696e6965766d2e65766d2e76312e4d736743615f8201527f6c6c222c00000000000000000000000000000000000000000000000000000000602082015250565b5f61160b6024836115a7565b9150611616826115b1565b602482019050919050565b7f2273656e646572223a20220000000000000000000000000000000000000000005f82015250565b5f611655600b836115a7565b915061166082611621565b600b82019050919050565b5f6116758261104f565b61167f81856115a7565b935061168f818560208601611069565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6116cf6002836115a7565b91506116da8261169b565b600282019050919050565b7f22636f6e74726163745f61646472223a202200000000000000000000000000005f82015250565b5f6117196012836115a7565b9150611724826116e5565b601282019050919050565b7f22696e707574223a2022000000000000000000000000000000000000000000005f82015250565b5f611763600a836115a7565b915061176e8261172f565b600a82019050919050565b7f2276616c7565223a202230222c000000000000000000000000000000000000005f82015250565b5f6117ad600d836115a7565b91506117b882611779565b600d82019050919050565b7f226163636573735f6c697374223a205b5d7d00000000000000000000000000005f82015250565b5f6117f76012836115a7565b9150611802826117c3565b601282019050919050565b5f611817826115ff565b915061182282611649565b915061182e828661166b565b9150611839826116c3565b91506118448261170d565b9150611850828561166b565b915061185b826116c3565b915061186682611757565b9150611872828461166b565b915061187d826116c3565b9150611888826117a1565b9150611893826117eb565b9150819050949350505050565b5f6118aa82610c89565b91506118b583610c89565b92508282026118c381610c89565b915082820484148315176118da576118d96110cf565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f61191882610c89565b91505f820361192a576119296110cf565b5b60018203905091905056fea264697066735822122060aa52ec760fc9185fa974ad5976987e48326a71a2def5f39d9e5df612dc877364736f6c63430008190033", } // CounterABI is the input ABI used to generate the binding from. diff --git a/x/evm/contracts/counter/Counter.sol b/x/evm/contracts/counter/Counter.sol index 7294e4d..12c7281 100644 --- a/x/evm/contracts/counter/Counter.sol +++ b/x/evm/contracts/counter/Counter.sol @@ -43,7 +43,7 @@ contract Counter is IIBCAsyncCallback { COSMOS_CONTRACT.execute_cosmos(exec_msg); if (call_revert) { - revert("revert"); + revert("revert reason dummy value for test"); } } diff --git a/x/evm/keeper/context.go b/x/evm/keeper/context.go index 91ebce7..ba01b8d 100644 --- a/x/evm/keeper/context.go +++ b/x/evm/keeper/context.go @@ -181,20 +181,21 @@ func (k Keeper) CreateEVM(ctx context.Context, caller common.Address, tracer *tr return ctx, nil, err } - vmConfig := vm.Config{ - Tracer: tracer, - ExtraEips: extraEIPs, - NumRetainBlockHashes: ¶ms.NumRetainBlockHashes, + chainConfig := types.DefaultChainConfig(ctx) + rules := chainConfig.Rules(blockContext.BlockNumber, blockContext.Random != nil, blockContext.Time) + vmConfig := vm.Config{Tracer: tracer, ExtraEips: extraEIPs, NumRetainBlockHashes: ¶ms.NumRetainBlockHashes} + precompiles, err := k.precompiles(rules, stateDB) + if err != nil { + return ctx, nil, err } *evm = *vm.NewEVMWithPrecompiles( blockContext, txContext, stateDB, - types.DefaultChainConfig(ctx), + chainConfig, vmConfig, - // use custom precompiles - k.Precompiles(stateDB), + precompiles, ) if tracer != nil { @@ -239,7 +240,7 @@ func (k Keeper) EVMStaticCallWithTracer(ctx context.Context, caller common.Addre sdkCtx := sdk.UnwrapSDKContext(ctx) gasBalance := k.computeGasLimit(sdkCtx) rules := evm.ChainConfig().Rules(evm.Context.BlockNumber, evm.Context.Random != nil, evm.Context.Time) - evm.StateDB.Prepare(rules, caller, types.NullAddress, &contractAddr, k.precompileAddrs, accessList) + evm.StateDB.Prepare(rules, caller, types.NullAddress, &contractAddr, k.precompileAddrs(rules), accessList) retBz, gasRemaining, err := evm.StaticCall( vm.AccountRef(caller), @@ -277,7 +278,7 @@ func (k Keeper) EVMCallWithTracer(ctx context.Context, caller common.Address, co } rules := evm.ChainConfig().Rules(evm.Context.BlockNumber, evm.Context.Random != nil, evm.Context.Time) - evm.StateDB.Prepare(rules, caller, types.NullAddress, &contractAddr, k.precompileAddrs, accessList) + evm.StateDB.Prepare(rules, caller, types.NullAddress, &contractAddr, k.precompileAddrs(rules), accessList) retBz, gasRemaining, err := evm.Call( vm.AccountRef(caller), @@ -371,7 +372,7 @@ func (k Keeper) EVMCreateWithTracer(ctx context.Context, caller common.Address, } rules := evm.ChainConfig().Rules(evm.Context.BlockNumber, evm.Context.Random != nil, evm.Context.Time) - evm.StateDB.Prepare(rules, caller, types.NullAddress, nil, k.precompileAddrs, accessList) + evm.StateDB.Prepare(rules, caller, types.NullAddress, nil, k.precompileAddrs(rules), accessList) var gasRemaining uint64 if salt == nil { diff --git a/x/evm/keeper/context_test.go b/x/evm/keeper/context_test.go index 497e28e..0748457 100644 --- a/x/evm/keeper/context_test.go +++ b/x/evm/keeper/context_test.go @@ -294,7 +294,8 @@ func Test_RevertAfterExecuteCosmos(t *testing.T) { require.NoError(t, err) _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) - require.ErrorContains(t, err, types.ErrReverted.Error()) + require.ErrorContains(t, err, vm.ErrExecutionReverted.Error()) + require.ErrorContains(t, err, "revert reason dummy value for test") // check balance require.Equal(t, amount, input.BankKeeper.GetBalance(ctx, sdk.AccAddress(contractAddr.Bytes()), denom).Amount) @@ -313,7 +314,7 @@ func Test_RevertAfterExecuteCosmos(t *testing.T) { require.NoError(t, err) _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) - require.NoError(t, err, types.ErrReverted.Error()) + require.NoError(t, err) require.Equal(t, math.ZeroInt(), input.BankKeeper.GetBalance(ctx, sdk.AccAddress(contractAddr.Bytes()), denom).Amount) require.Equal(t, amount, input.BankKeeper.GetBalance(ctx, addr, denom).Amount) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 6c53cf5..58cb461 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -12,7 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" evmconfig "github.com/initia-labs/minievm/x/evm/config" "github.com/initia-labs/minievm/x/evm/contracts/i_cosmos_callback" @@ -78,9 +77,6 @@ type Keeper struct { // evm stores EVMBlockHashes collections.Map[uint64, []byte] - precompiles vm.PrecompiledContracts - precompileAddrs []common.Address - queryCosmosWhitelist types.QueryCosmosWhitelist cosmosCallbackABI *abi.ABI } @@ -157,9 +153,6 @@ func NewKeeper( EVMBlockHashes: collections.NewMap(sb, types.EVMBlockHashPrefix, "evm_block_hashes", collections.Uint64Key, collections.BytesValue), - precompiles: vm.PrecompiledContracts{}, - precompileAddrs: []common.Address{}, - queryCosmosWhitelist: queryCosmosWhitelist, cosmosCallbackABI: cosmosCallbackABI, } @@ -189,11 +182,6 @@ func NewKeeper( k.txUtils = NewTxUtils(k) - // setup precompiles - if err := k.loadPrecompiles(); err != nil { - panic(err) - } - return k } diff --git a/x/evm/keeper/precompiles.go b/x/evm/keeper/precompiles.go index a303bf6..a554fdb 100644 --- a/x/evm/keeper/precompiles.go +++ b/x/evm/keeper/precompiles.go @@ -1,26 +1,24 @@ package keeper import ( - "math/big" - "slices" - + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/params" cosmosprecompile "github.com/initia-labs/minievm/x/evm/precompiles/cosmos" erc20registryprecompile "github.com/initia-labs/minievm/x/evm/precompiles/erc20_registry" "github.com/initia-labs/minievm/x/evm/types" ) -// loadPrecompiles loads the precompiled contracts. -func (k *Keeper) loadPrecompiles() error { - erc20RegistryPrecompile, err := erc20registryprecompile.NewERC20RegistryPrecompile(k.erc20StoresKeeper) +// precompiles returns the precompiled contracts for the EVM. +func (k *Keeper) precompiles(rules params.Rules, stateDB types.StateDB) (vm.PrecompiledContracts, error) { + erc20RegistryPrecompile, err := erc20registryprecompile.NewERC20RegistryPrecompile(stateDB, k.erc20StoresKeeper) if err != nil { - return err + return nil, err } cosmosPrecompile, err := cosmosprecompile.NewCosmosPrecompile( + stateDB, k.cdc, k.ac, k.accountKeeper, @@ -30,28 +28,19 @@ func (k *Keeper) loadPrecompiles() error { k.queryCosmosWhitelist, ) if err != nil { - return err + return nil, err } - // prepare precompiles; always use latest chain config - // to load all precompiles. - chainConfig := types.DefaultChainConfig(sdk.Context{}) - rules := chainConfig.Rules(big.NewInt(1), true, 1) - + // clone the active precompiles and add the new precompiles precompiles := vm.ActivePrecompiledContracts(rules) precompiles[types.CosmosPrecompileAddress] = cosmosPrecompile precompiles[types.ERC20RegistryPrecompileAddress] = erc20RegistryPrecompile - k.precompiles = precompiles - - precompileAddrs := slices.Clone(vm.ActivePrecompiles(rules)) - precompileAddrs = append(precompileAddrs, types.CosmosPrecompileAddress, types.ERC20RegistryPrecompileAddress) - k.precompileAddrs = precompileAddrs - return nil + return precompiles, nil } -func (k *Keeper) Precompiles(stateDB types.StateDB) vm.PrecompiledContracts { - k.precompiles[types.CosmosPrecompileAddress].(types.SetStateDB).SetStateDB(stateDB) - k.precompiles[types.ERC20RegistryPrecompileAddress].(types.SetStateDB).SetStateDB(stateDB) - return k.precompiles +// PrecompileAddrs returns the precompile addresses for the EVM. +func (k *Keeper) precompileAddrs(rules params.Rules) []common.Address { + addrs := append(vm.ActivePrecompiles(rules), types.CosmosPrecompileAddress, types.ERC20RegistryPrecompileAddress) + return addrs } diff --git a/x/evm/keeper/precompiles_test.go b/x/evm/keeper/precompiles_test.go index 26ed55d..45502ec 100644 --- a/x/evm/keeper/precompiles_test.go +++ b/x/evm/keeper/precompiles_test.go @@ -6,13 +6,18 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/initia-labs/minievm/x/evm/contracts/counter" "github.com/initia-labs/minievm/x/evm/contracts/i_cosmos" "github.com/initia-labs/minievm/x/evm/keeper" "github.com/initia-labs/minievm/x/evm/types" + "github.com/stretchr/testify/require" ) @@ -199,3 +204,46 @@ func Test_ToERC20(t *testing.T) { require.Equal(t, contractAddr, unpackedRet[0].(common.Address)) } + +func Test_PrecompileRevertError(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + + counterBz, err := hexutil.Decode(counter.CounterBin) + require.NoError(t, err) + + // deploy counter contract + caller := common.BytesToAddress(addr.Bytes()) + retBz, contractAddr, _, err := input.EVMKeeper.EVMCreate(ctx, caller, counterBz, nil, nil) + require.NoError(t, err) + require.NotEmpty(t, retBz) + require.Len(t, contractAddr, 20) + + // call execute cosmos function + parsed, err := counter.CounterMetaData.GetAbi() + require.NoError(t, err) + + denom := sdk.DefaultBondDenom + amount := math.NewInt(1000000000) + input.Faucet.Mint(ctx, contractAddr.Bytes(), sdk.NewCoin(denom, amount)) + + // call execute_cosmos with revert + inputBz, err := parsed.Pack("execute_cosmos", + fmt.Sprintf(`{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"%s","to_address":"%s","amount":[{"denom":"%s","amount":"%s"}]}`, + addr.String(), // try to call with wrong signer + addr.String(), // caller + denom, + amount, + ), + false, + ) + require.NoError(t, err) + + _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) + require.ErrorContains(t, err, vm.ErrExecutionReverted.Error()) + require.ErrorContains(t, err, sdkerrors.ErrUnauthorized.Error()) + + // check balance + require.Equal(t, amount, input.BankKeeper.GetBalance(ctx, sdk.AccAddress(contractAddr.Bytes()), denom).Amount) + require.Equal(t, math.ZeroInt(), input.BankKeeper.GetBalance(ctx, addr, denom).Amount) +} diff --git a/x/evm/precompiles/cosmos/contract.go b/x/evm/precompiles/cosmos/contract.go index 3ca9cf6..0990e8e 100644 --- a/x/evm/precompiles/cosmos/contract.go +++ b/x/evm/precompiles/cosmos/contract.go @@ -24,7 +24,16 @@ import ( var _ vm.ExtendedPrecompiledContract = &CosmosPrecompile{} var _ vm.PrecompiledContract = &CosmosPrecompile{} -var _ types.SetStateDB = &CosmosPrecompile{} + +var erc20CosmosABI *abi.ABI + +func init() { + var err error + erc20CosmosABI, err = i_cosmos.ICosmosMetaData.GetAbi() + if err != nil { + panic(err) + } +} type CosmosPrecompile struct { *abi.ABI @@ -42,6 +51,7 @@ type CosmosPrecompile struct { } func NewCosmosPrecompile( + stateDB types.StateDB, cdc codec.Codec, ac address.Codec, ak types.AccountKeeper, @@ -50,33 +60,25 @@ func NewCosmosPrecompile( grpcRouter types.GRPCRouter, queryWhitelist types.QueryCosmosWhitelist, ) (*CosmosPrecompile, error) { - abi, err := i_cosmos.ICosmosMetaData.GetAbi() - if err != nil { - return nil, err - } - return &CosmosPrecompile{ - ABI: abi, + ABI: erc20CosmosABI, cdc: cdc, ac: ac, ak: ak, bk: bk, edk: edk, + stateDB: stateDB, grpcRouter: grpcRouter, queryWhitelist: queryWhitelist, }, nil } -func (e *CosmosPrecompile) SetStateDB(stateDB types.StateDB) { - e.stateDB = stateDB -} - func (e *CosmosPrecompile) originAddress(ctx context.Context, addrBz []byte) (sdk.AccAddress, error) { account := e.ak.GetAccount(ctx, addrBz) if shorthandCallerAccount, ok := account.(types.ShorthandAccountI); ok { addr, err := shorthandCallerAccount.GetOriginalAddress(e.ac) if err != nil { - return nil, types.ErrPrecompileFailed.Wrap(err.Error()) + return nil, err } addrBz = addr.Bytes() @@ -103,6 +105,13 @@ func (e *CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, supp } if err != nil { + // convert cosmos error to EVM error + if err != vm.ErrOutOfGas { + resBz = types.NewRevertReason(err) + err = vm.ErrExecutionReverted + } + + // revert the stateDB to the snapshot e.stateDB.RevertToSnapshot(snapshot) } }() diff --git a/x/evm/precompiles/cosmos/contract_test.go b/x/evm/precompiles/cosmos/contract_test.go index e15ecf7..c802322 100644 --- a/x/evm/precompiles/cosmos/contract_test.go +++ b/x/evm/precompiles/cosmos/contract_test.go @@ -63,11 +63,9 @@ func setup() (sdk.Context, codec.Codec, address.Codec, types.AccountKeeper, type func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -109,11 +107,9 @@ func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) { func Test_CosmosPrecompile_IsModuleAddress(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -155,11 +151,9 @@ func Test_CosmosPrecompile_IsModuleAddress(t *testing.T) { func Test_CosmosPrecompile_ToCosmosAddress(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -186,11 +180,10 @@ func Test_CosmosPrecompile_ToCosmosAddress(t *testing.T) { func Test_CosmosPrecompile_ToEVMAddress(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -217,11 +210,10 @@ func Test_CosmosPrecompile_ToEVMAddress(t *testing.T) { func Test_ExecuteCosmos(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -250,7 +242,7 @@ func Test_ExecuteCosmos(t *testing.T) { // cannot call execute in readonly mode _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), true) - require.Error(t, err) + require.ErrorIs(t, err, vm.ErrExecutionReverted) // succeed _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) @@ -284,17 +276,16 @@ func Test_ExecuteCosmos(t *testing.T) { require.NoError(t, err) // failed with unauthorized error - _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) - require.ErrorContains(t, err, sdkerrors.ErrUnauthorized.Error()) + ret, _, err := cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) + require.ErrorIs(t, err, vm.ErrExecutionReverted) + require.Contains(t, types.NewRevertError(ret).Error(), sdkerrors.ErrUnauthorized.Error()) } func Test_ExecuteCosmosWithOptions(t *testing.T) { ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) - require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -324,7 +315,7 @@ func Test_ExecuteCosmosWithOptions(t *testing.T) { // cannot call execute in readonly mode _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), true) - require.Error(t, err) + require.ErrorIs(t, err, vm.ErrExecutionReverted) // succeed _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) @@ -358,8 +349,9 @@ func Test_ExecuteCosmosWithOptions(t *testing.T) { require.NoError(t, err) // failed with unauthorized error - _, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) - require.ErrorContains(t, err, sdkerrors.ErrUnauthorized.Error()) + ret, _, err := cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.EXECUTE_COSMOS_GAS+uint64(len(inputBz)), false) + require.ErrorIs(t, err, vm.ErrExecutionReverted) + require.Contains(t, types.NewRevertError(ret).Error(), sdkerrors.ErrUnauthorized.Error()) } func Test_QueryCosmos(t *testing.T) { @@ -377,7 +369,9 @@ func Test_QueryCosmos(t *testing.T) { }, }, } - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, MockGRPCRouter{ + + stateDB := NewMockStateDB(ctx) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, nil, MockGRPCRouter{ routes: map[string]baseapp.GRPCQueryHandler{ queryPath: func(ctx sdk.Context, req *abci.RequestQuery) (*abci.ResponseQuery, error) { resBz, err := cdc.Marshal(&expectedRet) @@ -399,9 +393,6 @@ func Test_QueryCosmos(t *testing.T) { }) require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) - evmAddr := common.HexToAddress("0x1") abi, err := contracts.ICosmosMetaData.GetAbi() @@ -436,7 +427,8 @@ func Test_ToDenom(t *testing.T) { erc20Addr := common.HexToAddress("0x123") denom := "evm/0000000000000000000000000000000000000123" - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, &MockERC20DenomKeeper{ + stateDB := NewMockStateDB(ctx) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, &MockERC20DenomKeeper{ denomMap: map[string]common.Address{ denom: erc20Addr, }, @@ -446,9 +438,6 @@ func Test_ToDenom(t *testing.T) { }, nil, nil) require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) - evmAddr := common.HexToAddress("0x1") abi, err := contracts.ICosmosMetaData.GetAbi() @@ -478,7 +467,8 @@ func Test_ToErc20(t *testing.T) { erc20Addr := common.HexToAddress("0x123") denom := "evm/0000000000000000000000000000000000000123" - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, &MockERC20DenomKeeper{ + stateDB := NewMockStateDB(ctx) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(stateDB, cdc, ac, ak, bk, &MockERC20DenomKeeper{ denomMap: map[string]common.Address{ denom: erc20Addr, }, @@ -488,9 +478,6 @@ func Test_ToErc20(t *testing.T) { }, nil, nil) require.NoError(t, err) - stateDB := NewMockStateDB(ctx) - cosmosPrecompile.SetStateDB(stateDB) - evmAddr := common.HexToAddress("0x1") abi, err := contracts.ICosmosMetaData.GetAbi() diff --git a/x/evm/precompiles/erc20_registry/contract.go b/x/evm/precompiles/erc20_registry/contract.go index 6e15c76..7b24eec 100644 --- a/x/evm/precompiles/erc20_registry/contract.go +++ b/x/evm/precompiles/erc20_registry/contract.go @@ -14,25 +14,25 @@ import ( var _ vm.ExtendedPrecompiledContract = &ERC20RegistryPrecompile{} var _ vm.PrecompiledContract = &ERC20RegistryPrecompile{} -var _ types.SetStateDB = &ERC20RegistryPrecompile{} -type ERC20RegistryPrecompile struct { - *abi.ABI - stateDB types.StateDB - k types.IERC20StoresKeeper -} +var erc20RegistryABI *abi.ABI -func NewERC20RegistryPrecompile(k types.IERC20StoresKeeper) (*ERC20RegistryPrecompile, error) { - abi, err := i_erc20_registry.IErc20RegistryMetaData.GetAbi() +func init() { + var err error + erc20RegistryABI, err = i_erc20_registry.IErc20RegistryMetaData.GetAbi() if err != nil { - return nil, err + panic(err) } +} - return &ERC20RegistryPrecompile{ABI: abi, k: k}, nil +type ERC20RegistryPrecompile struct { + *abi.ABI + stateDB types.StateDB + k types.IERC20StoresKeeper } -func (e *ERC20RegistryPrecompile) SetStateDB(stateDB types.StateDB) { - e.stateDB = stateDB +func NewERC20RegistryPrecompile(stateDB types.StateDB, k types.IERC20StoresKeeper) (*ERC20RegistryPrecompile, error) { + return &ERC20RegistryPrecompile{stateDB: stateDB, ABI: erc20RegistryABI, k: k}, nil } const ( @@ -60,6 +60,13 @@ func (e *ERC20RegistryPrecompile) ExtendedRun(caller vm.ContractRef, input []byt } if err != nil { + // convert cosmos error to EVM error + if err != vm.ErrOutOfGas { + resBz = types.NewRevertReason(err) + err = vm.ErrExecutionReverted + } + + // revert the stateDB to the snapshot e.stateDB.RevertToSnapshot(snapshot) } }() diff --git a/x/evm/precompiles/erc20_registry/contract_test.go b/x/evm/precompiles/erc20_registry/contract_test.go index 57126c9..e2d03df 100644 --- a/x/evm/precompiles/erc20_registry/contract_test.go +++ b/x/evm/precompiles/erc20_registry/contract_test.go @@ -71,12 +71,9 @@ func (e ERC20StoresKeeper) RegisterStore(ctx context.Context, addr sdk.AccAddres func Test_ERC20RegistryPrecompile(t *testing.T) { ctx, k := setup() - registry, err := precompiles.NewERC20RegistryPrecompile(k) - require.NoError(t, err) - - // set context stateDB := NewMockStateDB(ctx) - registry.SetStateDB(stateDB) + registry, err := precompiles.NewERC20RegistryPrecompile(stateDB, k) + require.NoError(t, err) erc20Addr := common.HexToAddress("0x1") accountAddr := common.HexToAddress("0x2") diff --git a/x/evm/types/errors.go b/x/evm/types/errors.go index c4faaff..a6cc556 100644 --- a/x/evm/types/errors.go +++ b/x/evm/types/errors.go @@ -1,9 +1,13 @@ package types import ( + "fmt" + errorsmod "cosmossdk.io/errors" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" ) // EVM Errors @@ -41,12 +45,36 @@ var ( ) func NewRevertError(revert []byte) error { - err := ErrReverted - reason, errUnpack := abi.UnpackRevert(revert) if errUnpack == nil { - return err.Wrapf("reason: %v, revert: %v", reason, hexutil.Encode(revert)) + return fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason) + } + + return ErrReverted.Wrapf("revert: %v", hexutil.Encode(revert)) +} + +// revertSelector is a special function selector for revert reason unpacking. +var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4] +var revertABIArguments abi.Arguments + +func init() { + revertABIType, err := abi.NewType("string", "", nil) + if err != nil { + panic(err) + } + + revertABIArguments = abi.Arguments{{Type: revertABIType}} +} + +func NewRevertReason(reason error) []byte { + bz, err := revertABIArguments.Pack(reason.Error()) + if err != nil { + panic(err) } - return err.Wrapf("revert: %v", hexutil.Encode(revert)) + ret := make([]byte, 4+len(bz)) + copy(ret, revertSelector) + copy(ret[4:], bz) + + return ret } diff --git a/x/evm/types/expected_keeper.go b/x/evm/types/expected_keeper.go index 85ecd85..cc53e25 100644 --- a/x/evm/types/expected_keeper.go +++ b/x/evm/types/expected_keeper.go @@ -90,10 +90,6 @@ type StateDB interface { ContextOfSnapshot(i int) sdk.Context } -type SetStateDB interface { - SetStateDB(stateDB StateDB) -} - type GRPCRouter interface { Route(path string) baseapp.GRPCQueryHandler }