diff --git a/x/evm/contracts/counter/Counter.go b/x/evm/contracts/counter/Counter.go index 9465040..2d83c78 100644 --- a/x/evm/contracts/counter/Counter.go +++ b/x/evm/contracts/counter/Counter.go @@ -31,8 +31,8 @@ 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\":\"uint256\",\"name\":\"oldCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCount\",\"type\":\"uint256\"}],\"name\":\"increased\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"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: "0x60806040526114f9806100115f395ff3fe60806040526004361061006f575f3560e01c8063619368951161004d57806361936895146100ed578063ac7fde5f14610115578063cad2355414610151578063e8927fbc1461018d5761006f565b806306661abd146100735780630d4f1f9d1461009d57806331a503f0146100c5575b5f80fd5b34801561007e575f80fd5b50610087610197565b6040516100949190610a32565b60405180910390f35b3480156100a8575f80fd5b506100c360048036038101906100be9190610ace565b61019c565b005b3480156100d0575f80fd5b506100eb60048036038101906100e69190610b0c565b6101e3565b005b3480156100f8575f80fd5b50610113600480360381019061010e9190610b0c565b610207565b005b348015610120575f80fd5b5061013b60048036038101906101369190610b0c565b610323565b6040516101489190610b4f565b60405180910390f35b34801561015c575f80fd5b5061017760048036038101906101729190610ca4565b610337565b6040516101849190610d7a565b60405180910390f35b6101956103c0565b005b5f5481565b80156101c8578167ffffffffffffffff165f808282546101bc9190610dc7565b925050819055506101df565b5f808154809291906101d990610dfa565b91905055505b5050565b8067ffffffffffffffff165f808282546101fd9190610dc7565b9250508190555050565b5f8167ffffffffffffffff1603156103205760f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e661023f8361041f565b6040518263ffffffff1660e01b815260040161025b9190610d7a565b6020604051808303815f875af1158015610277573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029b9190610e55565b5060f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66102c28361041f565b6040518263ffffffff1660e01b81526004016102de9190610d7a565b6020604051808303815f875af11580156102fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610e55565b505b50565b5f8167ffffffffffffffff16409050919050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b8152600401610375929190610e80565b5f604051808303815f875af1158015610390573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906103b89190610f23565b905092915050565b5f808154809291906103d190610dfa565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f546104059190610f6a565b5f54604051610415929190610f9d565b60405180910390a1565b606060f173ffffffffffffffffffffffffffffffffffffffff16636af32a55306040518263ffffffff1660e01b815260040161045b9190611003565b5f604051808303815f875af1158015610476573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061049e9190610f23565b6104a73061052b565b610503636193689560e01b6001866104bf919061101c565b6040516020016104cf9190611066565b6040516020818303038152906040526040516020016104ef92919061110e565b604051602081830303815290604052610558565b6040516020016105159392919061139b565b6040516020818303038152906040529050919050565b60606105518273ffffffffffffffffffffffffffffffffffffffff16601460ff166107dc565b9050919050565b60605f600280845161056a919061142e565b6105749190610dc7565b67ffffffffffffffff81111561058d5761058c610b80565b5b6040519080825280601f01601f1916602001820160405280156105bf5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106105f6576105f561146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106106595761065861146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f5b83518110156107d2575f8482815181106106a6576106a561146f565b5b602001015160f81c60f81b60f81c90507f303132333435363738396162636465660000000000000000000000000000000060048260ff16901c60ff16601081106106f3576106f261146f565b5b1a60f81b836002808502018151811061070f5761070e61146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f3031323334353637383961626364656600000000000000000000000000000000600f821660ff16601081106107765761077561146f565b5b1a60f81b8360026001600286020101815181106107965761079561146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350508080600101915050610689565b5080915050919050565b60605f8390505f60028460026107f2919061142e565b6107fc9190610dc7565b67ffffffffffffffff81111561081557610814610b80565b5b6040519080825280601f01601f1916602001820160405280156108475781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f8151811061087e5761087d61146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106108e1576108e061146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600185600261091f919061142e565b6109299190610dc7565b90505b60018111156109c8577f3031323334353637383961626364656600000000000000000000000000000000600f84166010811061096b5761096a61146f565b5b1a60f81b8282815181106109825761098161146f565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c9250806109c19061149c565b905061092c565b505f8214610a0f5784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401610a06929190610f9d565b60405180910390fd5b809250505092915050565b5f819050919050565b610a2c81610a1a565b82525050565b5f602082019050610a455f830184610a23565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b610a7881610a5c565b8114610a82575f80fd5b50565b5f81359050610a9381610a6f565b92915050565b5f8115159050919050565b610aad81610a99565b8114610ab7575f80fd5b50565b5f81359050610ac881610aa4565b92915050565b5f8060408385031215610ae457610ae3610a54565b5b5f610af185828601610a85565b9250506020610b0285828601610aba565b9150509250929050565b5f60208284031215610b2157610b20610a54565b5b5f610b2e84828501610a85565b91505092915050565b5f819050919050565b610b4981610b37565b82525050565b5f602082019050610b625f830184610b40565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610bb682610b70565b810181811067ffffffffffffffff82111715610bd557610bd4610b80565b5b80604052505050565b5f610be7610a4b565b9050610bf38282610bad565b919050565b5f67ffffffffffffffff821115610c1257610c11610b80565b5b610c1b82610b70565b9050602081019050919050565b828183375f83830152505050565b5f610c48610c4384610bf8565b610bde565b905082815260208101848484011115610c6457610c63610b6c565b5b610c6f848285610c28565b509392505050565b5f82601f830112610c8b57610c8a610b68565b5b8135610c9b848260208601610c36565b91505092915050565b5f8060408385031215610cba57610cb9610a54565b5b5f83013567ffffffffffffffff811115610cd757610cd6610a58565b5b610ce385828601610c77565b925050602083013567ffffffffffffffff811115610d0457610d03610a58565b5b610d1085828601610c77565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f610d4c82610d1a565b610d568185610d24565b9350610d66818560208601610d34565b610d6f81610b70565b840191505092915050565b5f6020820190508181035f830152610d928184610d42565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610dd182610a1a565b9150610ddc83610a1a565b9250828201905080821115610df457610df3610d9a565b5b92915050565b5f610e0482610a1a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610e3657610e35610d9a565b5b600182019050919050565b5f81519050610e4f81610aa4565b92915050565b5f60208284031215610e6a57610e69610a54565b5b5f610e7784828501610e41565b91505092915050565b5f6040820190508181035f830152610e988185610d42565b90508181036020830152610eac8184610d42565b90509392505050565b5f610ec7610ec284610bf8565b610bde565b905082815260208101848484011115610ee357610ee2610b6c565b5b610eee848285610d34565b509392505050565b5f82601f830112610f0a57610f09610b68565b5b8151610f1a848260208601610eb5565b91505092915050565b5f60208284031215610f3857610f37610a54565b5b5f82015167ffffffffffffffff811115610f5557610f54610a58565b5b610f6184828501610ef6565b91505092915050565b5f610f7482610a1a565b9150610f7f83610a1a565b9250828203905081811115610f9757610f96610d9a565b5b92915050565b5f604082019050610fb05f830185610a23565b610fbd6020830184610a23565b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610fed82610fc4565b9050919050565b610ffd81610fe3565b82525050565b5f6020820190506110165f830184610ff4565b92915050565b5f61102682610a5c565b915061103183610a5c565b9250828203905067ffffffffffffffff81111561105157611050610d9a565b5b92915050565b61106081610a5c565b82525050565b5f6020820190506110795f830184611057565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b5f819050919050565b6110c46110bf8261107f565b6110aa565b82525050565b5f81519050919050565b5f81905092915050565b5f6110e8826110ca565b6110f281856110d4565b9350611102818560208601610d34565b80840191505092915050565b5f61111982856110b3565b60048201915061112982846110de565b91508190509392505050565b5f81905092915050565b7f7b224074797065223a20222f6d696e6965766d2e65766d2e76312e4d736743615f8201527f6c6c222c00000000000000000000000000000000000000000000000000000000602082015250565b5f611199602483611135565b91506111a48261113f565b602482019050919050565b7f2273656e646572223a20220000000000000000000000000000000000000000005f82015250565b5f6111e3600b83611135565b91506111ee826111af565b600b82019050919050565b5f61120382610d1a565b61120d8185611135565b935061121d818560208601610d34565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f61125d600283611135565b915061126882611229565b600282019050919050565b7f22636f6e74726163745f61646472223a202200000000000000000000000000005f82015250565b5f6112a7601283611135565b91506112b282611273565b601282019050919050565b7f22696e707574223a2022000000000000000000000000000000000000000000005f82015250565b5f6112f1600a83611135565b91506112fc826112bd565b600a82019050919050565b7f2276616c7565223a202230222c000000000000000000000000000000000000005f82015250565b5f61133b600d83611135565b915061134682611307565b600d82019050919050565b7f226163636573735f6c697374223a205b5d7d00000000000000000000000000005f82015250565b5f611385601283611135565b915061139082611351565b601282019050919050565b5f6113a58261118d565b91506113b0826111d7565b91506113bc82866111f9565b91506113c782611251565b91506113d28261129b565b91506113de82856111f9565b91506113e982611251565b91506113f4826112e5565b915061140082846111f9565b915061140b82611251565b91506114168261132f565b915061142182611379565b9150819050949350505050565b5f61143882610a1a565b915061144383610a1a565b925082820261145181610a1a565b9150828204841483151761146857611467610d9a565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6114a682610a1a565b91505f82036114b8576114b7610d9a565b5b60018203905091905056fea2646970667358221220662342ef612cc67757c0cab65cd6080becaf1f776847bdde4dea3eff72d4342b64736f6c63430008190033", + 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\":\"uint256\",\"name\":\"oldCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCount\",\"type\":\"uint256\"}],\"name\":\"increased\",\"type\":\"event\"},{\"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\":\"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: "0x60806040526116ae806100115f395ff3fe60806040526004361061007a575f3560e01c8063619368951161004d5780636193689514610120578063ac7fde5f14610148578063cad2355414610184578063e8927fbc146101c05761007a565b806306661abd1461007e5780630d4f1f9d146100a857806324c68fce146100d057806331a503f0146100f8575b5f80fd5b348015610089575f80fd5b506100926101ca565b60405161009f9190610b25565b60405180910390f35b3480156100b3575f80fd5b506100ce60048036038101906100c99190610bc1565b6101cf565b005b3480156100db575f80fd5b506100f660048036038101906100f19190610d3b565b610216565b005b348015610103575f80fd5b5061011e60048036038101906101199190610d95565b6102d6565b005b34801561012b575f80fd5b5061014660048036038101906101419190610d95565b6102fa565b005b348015610153575f80fd5b5061016e60048036038101906101699190610d95565b610416565b60405161017b9190610dd8565b60405180910390f35b34801561018f575f80fd5b506101aa60048036038101906101a59190610df1565b61042a565b6040516101b79190610ec7565b60405180910390f35b6101c86104b3565b005b5f5481565b80156101fb578167ffffffffffffffff165f808282546101ef9190610f14565b92505081905550610212565b5f8081548092919061020c90610f47565b91905055505b5050565b60f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e6836040518263ffffffff1660e01b81526004016102509190610ec7565b6020604051808303815f875af115801561026c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102909190610fa2565b5080156102d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c990611017565b60405180910390fd5b5050565b8067ffffffffffffffff165f808282546102f09190610f14565b9250508190555050565b5f8167ffffffffffffffff1603156104135760f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e661033283610512565b6040518263ffffffff1660e01b815260040161034e9190610ec7565b6020604051808303815f875af115801561036a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038e9190610fa2565b5060f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e66103b583610512565b6040518263ffffffff1660e01b81526004016103d19190610ec7565b6020604051808303815f875af11580156103ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104119190610fa2565b505b50565b5f8167ffffffffffffffff16409050919050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b8152600401610468929190611035565b5f604051808303815f875af1158015610483573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906104ab91906110d8565b905092915050565b5f808154809291906104c490610f47565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f546104f8919061111f565b5f54604051610508929190611152565b60405180910390a1565b606060f173ffffffffffffffffffffffffffffffffffffffff16636af32a55306040518263ffffffff1660e01b815260040161054e91906111b8565b5f604051808303815f875af1158015610569573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061059191906110d8565b61059a3061061e565b6105f6636193689560e01b6001866105b291906111d1565b6040516020016105c2919061121b565b6040516020818303038152906040526040516020016105e29291906112c3565b60405160208183030381529060405261064b565b60405160200161060893929190611550565b6040516020818303038152906040529050919050565b60606106448273ffffffffffffffffffffffffffffffffffffffff16601460ff166108cf565b9050919050565b60605f600280845161065d91906115e3565b6106679190610f14565b67ffffffffffffffff8111156106805761067f610c17565b5b6040519080825280601f01601f1916602001820160405280156106b25781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106106e9576106e8611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061074c5761074b611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f5b83518110156108c5575f84828151811061079957610798611624565b5b602001015160f81c60f81b60f81c90507f303132333435363738396162636465660000000000000000000000000000000060048260ff16901c60ff16601081106107e6576107e5611624565b5b1a60f81b836002808502018151811061080257610801611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f3031323334353637383961626364656600000000000000000000000000000000600f821660ff166010811061086957610868611624565b5b1a60f81b83600260016002860201018151811061088957610888611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535050808060010191505061077c565b5080915050919050565b60605f8390505f60028460026108e591906115e3565b6108ef9190610f14565b67ffffffffffffffff81111561090857610907610c17565b5b6040519080825280601f01601f19166020018201604052801561093a5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f8151811061097157610970611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106109d4576109d3611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f6001856002610a1291906115e3565b610a1c9190610f14565b90505b6001811115610abb577f3031323334353637383961626364656600000000000000000000000000000000600f841660108110610a5e57610a5d611624565b5b1a60f81b828281518110610a7557610a74611624565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c925080610ab490611651565b9050610a1f565b505f8214610b025784846040517fe22e27eb000000000000000000000000000000000000000000000000000000008152600401610af9929190611152565b60405180910390fd5b809250505092915050565b5f819050919050565b610b1f81610b0d565b82525050565b5f602082019050610b385f830184610b16565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b610b6b81610b4f565b8114610b75575f80fd5b50565b5f81359050610b8681610b62565b92915050565b5f8115159050919050565b610ba081610b8c565b8114610baa575f80fd5b50565b5f81359050610bbb81610b97565b92915050565b5f8060408385031215610bd757610bd6610b47565b5b5f610be485828601610b78565b9250506020610bf585828601610bad565b9150509250929050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610c4d82610c07565b810181811067ffffffffffffffff82111715610c6c57610c6b610c17565b5b80604052505050565b5f610c7e610b3e565b9050610c8a8282610c44565b919050565b5f67ffffffffffffffff821115610ca957610ca8610c17565b5b610cb282610c07565b9050602081019050919050565b828183375f83830152505050565b5f610cdf610cda84610c8f565b610c75565b905082815260208101848484011115610cfb57610cfa610c03565b5b610d06848285610cbf565b509392505050565b5f82601f830112610d2257610d21610bff565b5b8135610d32848260208601610ccd565b91505092915050565b5f8060408385031215610d5157610d50610b47565b5b5f83013567ffffffffffffffff811115610d6e57610d6d610b4b565b5b610d7a85828601610d0e565b9250506020610d8b85828601610bad565b9150509250929050565b5f60208284031215610daa57610da9610b47565b5b5f610db784828501610b78565b91505092915050565b5f819050919050565b610dd281610dc0565b82525050565b5f602082019050610deb5f830184610dc9565b92915050565b5f8060408385031215610e0757610e06610b47565b5b5f83013567ffffffffffffffff811115610e2457610e23610b4b565b5b610e3085828601610d0e565b925050602083013567ffffffffffffffff811115610e5157610e50610b4b565b5b610e5d85828601610d0e565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f610e9982610e67565b610ea38185610e71565b9350610eb3818560208601610e81565b610ebc81610c07565b840191505092915050565b5f6020820190508181035f830152610edf8184610e8f565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610f1e82610b0d565b9150610f2983610b0d565b9250828201905080821115610f4157610f40610ee7565b5b92915050565b5f610f5182610b0d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f8357610f82610ee7565b5b600182019050919050565b5f81519050610f9c81610b97565b92915050565b5f60208284031215610fb757610fb6610b47565b5b5f610fc484828501610f8e565b91505092915050565b7f72657665727400000000000000000000000000000000000000000000000000005f82015250565b5f611001600683610e71565b915061100c82610fcd565b602082019050919050565b5f6020820190508181035f83015261102e81610ff5565b9050919050565b5f6040820190508181035f83015261104d8185610e8f565b905081810360208301526110618184610e8f565b90509392505050565b5f61107c61107784610c8f565b610c75565b90508281526020810184848401111561109857611097610c03565b5b6110a3848285610e81565b509392505050565b5f82601f8301126110bf576110be610bff565b5b81516110cf84826020860161106a565b91505092915050565b5f602082840312156110ed576110ec610b47565b5b5f82015167ffffffffffffffff81111561110a57611109610b4b565b5b611116848285016110ab565b91505092915050565b5f61112982610b0d565b915061113483610b0d565b925082820390508181111561114c5761114b610ee7565b5b92915050565b5f6040820190506111655f830185610b16565b6111726020830184610b16565b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6111a282611179565b9050919050565b6111b281611198565b82525050565b5f6020820190506111cb5f8301846111a9565b92915050565b5f6111db82610b4f565b91506111e683610b4f565b9250828203905067ffffffffffffffff81111561120657611205610ee7565b5b92915050565b61121581610b4f565b82525050565b5f60208201905061122e5f83018461120c565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b5f819050919050565b61127961127482611234565b61125f565b82525050565b5f81519050919050565b5f81905092915050565b5f61129d8261127f565b6112a78185611289565b93506112b7818560208601610e81565b80840191505092915050565b5f6112ce8285611268565b6004820191506112de8284611293565b91508190509392505050565b5f81905092915050565b7f7b224074797065223a20222f6d696e6965766d2e65766d2e76312e4d736743615f8201527f6c6c222c00000000000000000000000000000000000000000000000000000000602082015250565b5f61134e6024836112ea565b9150611359826112f4565b602482019050919050565b7f2273656e646572223a20220000000000000000000000000000000000000000005f82015250565b5f611398600b836112ea565b91506113a382611364565b600b82019050919050565b5f6113b882610e67565b6113c281856112ea565b93506113d2818560208601610e81565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6114126002836112ea565b915061141d826113de565b600282019050919050565b7f22636f6e74726163745f61646472223a202200000000000000000000000000005f82015250565b5f61145c6012836112ea565b915061146782611428565b601282019050919050565b7f22696e707574223a2022000000000000000000000000000000000000000000005f82015250565b5f6114a6600a836112ea565b91506114b182611472565b600a82019050919050565b7f2276616c7565223a202230222c000000000000000000000000000000000000005f82015250565b5f6114f0600d836112ea565b91506114fb826114bc565b600d82019050919050565b7f226163636573735f6c697374223a205b5d7d00000000000000000000000000005f82015250565b5f61153a6012836112ea565b915061154582611506565b601282019050919050565b5f61155a82611342565b91506115658261138c565b915061157182866113ae565b915061157c82611406565b915061158782611450565b915061159382856113ae565b915061159e82611406565b91506115a98261149a565b91506115b582846113ae565b91506115c082611406565b91506115cb826114e4565b91506115d68261152e565b9150819050949350505050565b5f6115ed82610b0d565b91506115f883610b0d565b925082820261160681610b0d565b9150828204841483151761161d5761161c610ee7565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f61165b82610b0d565b91505f820361166d5761166c610ee7565b5b60018203905091905056fea26469706673582212200f9b2329e990c3d38bc433416075d3d4335c8a2f4bc402cc0a9615513a336d1d64736f6c63430008190033", } // CounterABI is the input ABI used to generate the binding from. @@ -264,6 +264,27 @@ func (_Counter *CounterCallerSession) GetBlockhash(n uint64) ([32]byte, error) { return _Counter.Contract.GetBlockhash(&_Counter.CallOpts, n) } +// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce. +// +// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns() +func (_Counter *CounterTransactor) ExecuteCosmos(opts *bind.TransactOpts, exec_msg string, call_revert bool) (*types.Transaction, error) { + return _Counter.contract.Transact(opts, "execute_cosmos", exec_msg, call_revert) +} + +// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce. +// +// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns() +func (_Counter *CounterSession) ExecuteCosmos(exec_msg string, call_revert bool) (*types.Transaction, error) { + return _Counter.Contract.ExecuteCosmos(&_Counter.TransactOpts, exec_msg, call_revert) +} + +// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce. +// +// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns() +func (_Counter *CounterTransactorSession) ExecuteCosmos(exec_msg string, call_revert bool) (*types.Transaction, error) { + return _Counter.Contract.ExecuteCosmos(&_Counter.TransactOpts, exec_msg, call_revert) +} + // IbcAck is a paid mutator transaction binding the contract method 0x0d4f1f9d. // // Solidity: function ibc_ack(uint64 callback_id, bool success) returns() diff --git a/x/evm/contracts/counter/Counter.sol b/x/evm/contracts/counter/Counter.sol index 0eeedd1..699efd6 100644 --- a/x/evm/contracts/counter/Counter.sol +++ b/x/evm/contracts/counter/Counter.sol @@ -37,6 +37,17 @@ contract Counter is IIBCAsyncCallback { return COSMOS_CONTRACT.query_cosmos(path, req); } + function execute_cosmos( + string memory exec_msg, + bool call_revert + ) external { + COSMOS_CONTRACT.execute_cosmos(exec_msg); + + if (call_revert) { + revert("revert"); + } + } + function get_blockhash(uint64 n) external view returns (bytes32) { return blockhash(n); } diff --git a/x/evm/keeper/context.go b/x/evm/keeper/context.go index 870cad4..927bcad 100644 --- a/x/evm/keeper/context.go +++ b/x/evm/keeper/context.go @@ -161,6 +161,12 @@ func (k Keeper) CreateEVM(ctx context.Context, caller common.Address, tracer *tr return ctx, nil, err } + // prepare SDK context for EVM execution + ctx, err = prepareSDKContext(sdk.UnwrapSDKContext(ctx)) + if err != nil { + return ctx, nil, err + } + evm := &vm.EVM{} blockContext, err := k.buildBlockContext(ctx, evm, fee) if err != nil { @@ -181,19 +187,13 @@ func (k Keeper) CreateEVM(ctx context.Context, caller common.Address, tracer *tr NumRetainBlockHashes: ¶ms.NumRetainBlockHashes, } - // prepare SDK context for EVM execution - ctx, err = prepareSDKContext(sdk.UnwrapSDKContext(ctx)) - if err != nil { - return ctx, nil, err - } - *evm = *vm.NewEVMWithPrecompiles( blockContext, txContext, stateDB, types.DefaultChainConfig(ctx), vmConfig, - k.precompiles.toMap(ctx), + k.precompiles.toMap(stateDB), ) if tracer != nil { diff --git a/x/evm/keeper/context_test.go b/x/evm/keeper/context_test.go index dfeb0ca..9a73f75 100644 --- a/x/evm/keeper/context_test.go +++ b/x/evm/keeper/context_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "fmt" "strings" "testing" @@ -237,3 +238,63 @@ func Test_RecursiveDepth(t *testing.T) { _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) require.ErrorContains(t, err, types.ErrExceedMaxRecursiveDepth.Error()) } + +func Test_RevertAfterExecuteCosmos(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"}]}`, + sdk.AccAddress(contractAddr.Bytes()).String(), + addr.String(), // caller + denom, + amount, + ), + true, + ) + require.NoError(t, err) + + _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) + require.ErrorContains(t, err, types.ErrReverted.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) + + // call execute_cosmos without 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"}]}`, + sdk.AccAddress(contractAddr.Bytes()).String(), + addr.String(), // caller + denom, + amount, + ), + false, + ) + require.NoError(t, err) + + _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil) + require.NoError(t, err, types.ErrReverted.Error()) + + 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/precompiles.go b/x/evm/keeper/precompiles.go index 5f7a39c..e290b68 100644 --- a/x/evm/keeper/precompiles.go +++ b/x/evm/keeper/precompiles.go @@ -1,8 +1,6 @@ package keeper import ( - "context" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -55,10 +53,10 @@ func (k *Keeper) loadPrecompiles() error { type precompiles []precompile // toMap converts the precompiles to a map. -func (ps precompiles) toMap(ctx context.Context) map[common.Address]vm.PrecompiledContract { +func (ps precompiles) toMap(stateDB types.StateDB) map[common.Address]vm.PrecompiledContract { m := make(map[common.Address]vm.PrecompiledContract) for _, p := range ps { - m[p.addr] = p.contract.(types.WithContext).WithContext(ctx) + m[p.addr] = p.contract.(types.WithStateDB).WithStateDB(stateDB) } return m diff --git a/x/evm/precompiles/cosmos/common_test.go b/x/evm/precompiles/cosmos/common_test.go new file mode 100644 index 0000000..f52d9e2 --- /dev/null +++ b/x/evm/precompiles/cosmos/common_test.go @@ -0,0 +1,352 @@ +package cosmosprecompile_test + +import ( + "context" + + "cosmossdk.io/core/address" + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/stateless" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie/utils" + "github.com/holiman/uint256" + + "github.com/initia-labs/minievm/x/evm/state" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var _ evmtypes.StateDB = &MockStateDB{} + +type MockStateDB struct { + ctx sdk.Context + initialCtx sdk.Context + + // Snapshot stack + snaps []*state.Snapshot +} + +func NewMockStateDB(ctx sdk.Context) *MockStateDB { + return &MockStateDB{ + ctx: ctx, + initialCtx: ctx, + } +} + +// Snapshot implements types.StateDB. +func (m *MockStateDB) Snapshot() int { + // get a current snapshot id + sid := len(m.snaps) - 1 + + // create a new snapshot + snap := state.NewSnapshot(m.ctx) + m.snaps = append(m.snaps, snap) + + // use the new snapshot context + m.ctx = snap.Context() + + // return the current snapshot id + return sid +} + +// RevertToSnapshot implements types.StateDB. +func (m *MockStateDB) RevertToSnapshot(i int) { + if i == -1 { + m.ctx = m.initialCtx + m.snaps = m.snaps[:0] + return + } + + // revert to the snapshot with the given id + snap := m.snaps[i] + m.ctx = snap.Context() + + // clear the snapshots after the given id + m.snaps = m.snaps[:i] +} + +// ContextOfSnapshot implements types.StateDB. +func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context { + if i == -1 { + return m.initialCtx + } + + return m.snaps[i].Context() +} + +//////////////////////// MOCKED METHODS //////////////////////// + +// AddAddressToAccessList implements types.StateDB. +func (m *MockStateDB) AddAddressToAccessList(addr common.Address) { + panic("unimplemented") +} + +// AddBalance implements types.StateDB. +func (m *MockStateDB) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) { + panic("unimplemented") +} + +// AddLog implements types.StateDB. +func (m *MockStateDB) AddLog(*types.Log) { + panic("unimplemented") +} + +// AddPreimage implements types.StateDB. +func (m *MockStateDB) AddPreimage(common.Hash, []byte) { + panic("unimplemented") +} + +// AddRefund implements types.StateDB. +func (m *MockStateDB) AddRefund(uint64) { + panic("unimplemented") +} + +// AddSlotToAccessList implements types.StateDB. +func (m *MockStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { + panic("unimplemented") +} + +// AddressInAccessList implements types.StateDB. +func (m *MockStateDB) AddressInAccessList(addr common.Address) bool { + panic("unimplemented") +} + +// CreateAccount implements types.StateDB. +func (m *MockStateDB) CreateAccount(common.Address) { + panic("unimplemented") +} + +// CreateContract implements types.StateDB. +func (m *MockStateDB) CreateContract(common.Address) { + panic("unimplemented") +} + +// Empty implements types.StateDB. +func (m *MockStateDB) Empty(common.Address) bool { + panic("unimplemented") +} + +// Exist implements types.StateDB. +func (m *MockStateDB) Exist(common.Address) bool { + panic("unimplemented") +} + +// GetBalance implements types.StateDB. +func (m *MockStateDB) GetBalance(common.Address) *uint256.Int { + panic("unimplemented") +} + +// GetCode implements types.StateDB. +func (m *MockStateDB) GetCode(common.Address) []byte { + panic("unimplemented") +} + +// GetCodeHash implements types.StateDB. +func (m *MockStateDB) GetCodeHash(common.Address) common.Hash { + panic("unimplemented") +} + +// GetCodeSize implements types.StateDB. +func (m *MockStateDB) GetCodeSize(common.Address) int { + panic("unimplemented") +} + +// GetCommittedState implements types.StateDB. +func (m *MockStateDB) GetCommittedState(common.Address, common.Hash) common.Hash { + panic("unimplemented") +} + +// GetNonce implements types.StateDB. +func (m *MockStateDB) GetNonce(common.Address) uint64 { + panic("unimplemented") +} + +// GetRefund implements types.StateDB. +func (m *MockStateDB) GetRefund() uint64 { + panic("unimplemented") +} + +// GetState implements types.StateDB. +func (m *MockStateDB) GetState(common.Address, common.Hash) common.Hash { + panic("unimplemented") +} + +// GetStorageRoot implements types.StateDB. +func (m *MockStateDB) GetStorageRoot(addr common.Address) common.Hash { + panic("unimplemented") +} + +// GetTransientState implements types.StateDB. +func (m *MockStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { + panic("unimplemented") +} + +// HasSelfDestructed implements types.StateDB. +func (m *MockStateDB) HasSelfDestructed(common.Address) bool { + panic("unimplemented") +} + +// PointCache implements types.StateDB. +func (m *MockStateDB) PointCache() *utils.PointCache { + panic("unimplemented") +} + +// Prepare implements types.StateDB. +func (m *MockStateDB) Prepare(rules params.Rules, sender common.Address, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) { + panic("unimplemented") +} + +// SelfDestruct implements types.StateDB. +func (m *MockStateDB) SelfDestruct(common.Address) { + panic("unimplemented") +} + +// Selfdestruct6780 implements types.StateDB. +func (m *MockStateDB) Selfdestruct6780(common.Address) { + panic("unimplemented") +} + +// SetCode implements types.StateDB. +func (m *MockStateDB) SetCode(common.Address, []byte) { + panic("unimplemented") +} + +// SetNonce implements types.StateDB. +func (m *MockStateDB) SetNonce(common.Address, uint64) { + panic("unimplemented") +} + +// SetState implements types.StateDB. +func (m *MockStateDB) SetState(common.Address, common.Hash, common.Hash) { + panic("unimplemented") +} + +// SetTransientState implements types.StateDB. +func (m *MockStateDB) SetTransientState(addr common.Address, key common.Hash, value common.Hash) { + panic("unimplemented") +} + +// SlotInAccessList implements types.StateDB. +func (m *MockStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { + panic("unimplemented") +} + +// SubBalance implements types.StateDB. +func (m *MockStateDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) { + panic("unimplemented") +} + +// SubRefund implements types.StateDB. +func (m *MockStateDB) SubRefund(uint64) { + panic("unimplemented") +} + +// Witness implements types.StateDB. +func (m *MockStateDB) Witness() *stateless.Witness { + panic("unimplemented") +} + +var _ evmtypes.AccountKeeper = &MockAccountKeeper{} + +// mock account keeper for testing +type MockAccountKeeper struct { + ac address.Codec + accounts map[string]sdk.AccountI +} + +// GetAccount implements types.AccountKeeper. +func (k MockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + str, _ := k.ac.BytesToString(addr.Bytes()) + return k.accounts[str] +} + +// HasAccount implements types.AccountKeeper. +func (k MockAccountKeeper) HasAccount(ctx context.Context, addr sdk.AccAddress) bool { + str, _ := k.ac.BytesToString(addr.Bytes()) + _, ok := k.accounts[str] + return ok +} + +// NewAccount implements types.AccountKeeper. +func (k *MockAccountKeeper) NewAccount(ctx context.Context, acc sdk.AccountI) sdk.AccountI { + acc.SetAccountNumber(uint64(len(k.accounts))) + return acc +} + +// NewAccountWithAddress implements types.AccountKeeper. +func (k MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + return authtypes.NewBaseAccount(addr, nil, uint64(len(k.accounts)), 0) +} + +// NextAccountNumber implements types.AccountKeeper. +func (k MockAccountKeeper) NextAccountNumber(ctx context.Context) uint64 { + return uint64(len(k.accounts)) +} + +// SetAccount implements types.AccountKeeper. +func (k MockAccountKeeper) SetAccount(ctx context.Context, acc sdk.AccountI) { + str, _ := k.ac.BytesToString(acc.GetAddress().Bytes()) + k.accounts[str] = acc +} + +// RemoveAccount implements types.AccountKeeper. +func (k MockAccountKeeper) RemoveAccount(ctx context.Context, acc sdk.AccountI) { + str, _ := k.ac.BytesToString(acc.GetAddress().Bytes()) + delete(k.accounts, str) +} + +var _ evmtypes.BankKeeper = &MockBankKeeper{} + +// mock bank keeper for testing +type MockBankKeeper struct { + ac address.Codec + blockedAddresses map[string]bool +} + +// BlockedAddr implements types.BankKeeper. +func (k MockBankKeeper) BlockedAddr(addr sdk.AccAddress) bool { + str, _ := k.ac.BytesToString(addr.Bytes()) + return k.blockedAddresses[str] +} + +var _ evmtypes.GRPCRouter = MockGRPCRouter{} + +type MockGRPCRouter struct { + routes map[string]baseapp.GRPCQueryHandler +} + +func (router MockGRPCRouter) Route(path string) baseapp.GRPCQueryHandler { + return router.routes[path] +} + +var _ evmtypes.ERC20DenomKeeper = &MockERC20DenomKeeper{} + +type MockERC20DenomKeeper struct { + denomMap map[string]common.Address + addrMap map[common.Address]string +} + +// GetContractAddrByDenom implements types.ERC20DenomKeeper. +func (e *MockERC20DenomKeeper) GetContractAddrByDenom(_ context.Context, denom string) (common.Address, error) { + addr, found := e.denomMap[denom] + if !found { + return common.Address{}, sdkerrors.ErrNotFound + } + + return addr, nil +} + +// GetDenomByContractAddr implements types.ERC20DenomKeeper. +func (e *MockERC20DenomKeeper) GetDenomByContractAddr(_ context.Context, addr common.Address) (string, error) { + denom, found := e.addrMap[addr] + if !found { + return "", sdkerrors.ErrNotFound + } + + return denom, nil +} diff --git a/x/evm/precompiles/cosmos/contract.go b/x/evm/precompiles/cosmos/contract.go index 78faf3a..33e42e2 100644 --- a/x/evm/precompiles/cosmos/contract.go +++ b/x/evm/precompiles/cosmos/contract.go @@ -24,14 +24,14 @@ import ( var _ vm.ExtendedPrecompiledContract = CosmosPrecompile{} var _ vm.PrecompiledContract = CosmosPrecompile{} -var _ types.WithContext = CosmosPrecompile{} +var _ types.WithStateDB = CosmosPrecompile{} type CosmosPrecompile struct { *abi.ABI - ctx context.Context - cdc codec.Codec - ac address.Codec + stateDB types.StateDB + cdc codec.Codec + ac address.Codec ak types.AccountKeeper bk types.BankKeeper @@ -67,8 +67,8 @@ func NewCosmosPrecompile( }, nil } -func (e CosmosPrecompile) WithContext(ctx context.Context) vm.PrecompiledContract { - e.ctx = ctx +func (e CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract { + e.stateDB = stateDB return e } @@ -88,6 +88,9 @@ func (e CosmosPrecompile) originAddress(ctx context.Context, addrBz []byte) (sdk // ExtendedRun implements vm.ExtendedPrecompiledContract. func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppliedGas uint64, readOnly bool) (resBz []byte, usedGas uint64, err error) { + snapshot := e.stateDB.Snapshot() + ctx := e.stateDB.ContextOfSnapshot(snapshot).WithGasMeter(storetypes.NewGasMeter(suppliedGas)) + defer func() { if r := recover(); r != nil { switch r.(type) { @@ -99,6 +102,10 @@ func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppl panic(r) } } + + if err != nil { + e.stateDB.RevertToSnapshot(snapshot) + } }() method, err := e.ABI.MethodById(input) @@ -111,8 +118,6 @@ func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppl return nil, 0, types.ErrPrecompileFailed.Wrap(err.Error()) } - ctx := sdk.UnwrapSDKContext(e.ctx).WithGasMeter(storetypes.NewGasMeter(suppliedGas)) - // charge input gas ctx.GasMeter().ConsumeGas(storetypes.Gas(len(input))*GAS_PER_BYTE, "input bytes") diff --git a/x/evm/precompiles/cosmos/contract_test.go b/x/evm/precompiles/cosmos/contract_test.go index e319d5b..07ad717 100644 --- a/x/evm/precompiles/cosmos/contract_test.go +++ b/x/evm/precompiles/cosmos/contract_test.go @@ -1,7 +1,6 @@ package cosmosprecompile_test import ( - "context" "fmt" "testing" "time" @@ -67,7 +66,8 @@ func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) { cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -112,7 +112,8 @@ func Test_CosmosPrecompile_IsModuleAddress(t *testing.T) { cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -157,7 +158,8 @@ func Test_CosmosPrecompile_ToCosmosAddress(t *testing.T) { cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -187,7 +189,8 @@ func Test_CosmosPrecompile_ToEVMAddress(t *testing.T) { cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -217,7 +220,8 @@ func Test_ExecuteCosmos(t *testing.T) { cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) @@ -316,7 +320,8 @@ func Test_QueryCosmos(t *testing.T) { }) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") @@ -362,7 +367,8 @@ func Test_ToDenom(t *testing.T) { }, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") @@ -403,7 +409,8 @@ func Test_ToErc20(t *testing.T) { }, nil, nil) require.NoError(t, err) - cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + stateDB := NewMockStateDB(ctx) + cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile) evmAddr := common.HexToAddress("0x1") @@ -427,103 +434,3 @@ func Test_ToErc20(t *testing.T) { require.NoError(t, err) require.Equal(t, erc20Addr, unpackedRet[0].(common.Address)) } - -var _ types.AccountKeeper = &MockAccountKeeper{} - -// mock account keeper for testing -type MockAccountKeeper struct { - ac address.Codec - accounts map[string]sdk.AccountI -} - -// GetAccount implements types.AccountKeeper. -func (k MockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { - str, _ := k.ac.BytesToString(addr.Bytes()) - return k.accounts[str] -} - -// HasAccount implements types.AccountKeeper. -func (k MockAccountKeeper) HasAccount(ctx context.Context, addr sdk.AccAddress) bool { - str, _ := k.ac.BytesToString(addr.Bytes()) - _, ok := k.accounts[str] - return ok -} - -// NewAccount implements types.AccountKeeper. -func (k *MockAccountKeeper) NewAccount(ctx context.Context, acc sdk.AccountI) sdk.AccountI { - acc.SetAccountNumber(uint64(len(k.accounts))) - return acc -} - -// NewAccountWithAddress implements types.AccountKeeper. -func (k MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { - return authtypes.NewBaseAccount(addr, nil, uint64(len(k.accounts)), 0) -} - -// NextAccountNumber implements types.AccountKeeper. -func (k MockAccountKeeper) NextAccountNumber(ctx context.Context) uint64 { - return uint64(len(k.accounts)) -} - -// SetAccount implements types.AccountKeeper. -func (k MockAccountKeeper) SetAccount(ctx context.Context, acc sdk.AccountI) { - str, _ := k.ac.BytesToString(acc.GetAddress().Bytes()) - k.accounts[str] = acc -} - -// RemoveAccount implements types.AccountKeeper. -func (k MockAccountKeeper) RemoveAccount(ctx context.Context, acc sdk.AccountI) { - str, _ := k.ac.BytesToString(acc.GetAddress().Bytes()) - delete(k.accounts, str) -} - -var _ types.BankKeeper = &MockBankKeeper{} - -// mock bank keeper for testing -type MockBankKeeper struct { - ac address.Codec - blockedAddresses map[string]bool -} - -// BlockedAddr implements types.BankKeeper. -func (k MockBankKeeper) BlockedAddr(addr sdk.AccAddress) bool { - str, _ := k.ac.BytesToString(addr.Bytes()) - return k.blockedAddresses[str] -} - -var _ types.GRPCRouter = MockGRPCRouter{} - -type MockGRPCRouter struct { - routes map[string]baseapp.GRPCQueryHandler -} - -func (router MockGRPCRouter) Route(path string) baseapp.GRPCQueryHandler { - return router.routes[path] -} - -var _ types.ERC20DenomKeeper = &MockERC20DenomKeeper{} - -type MockERC20DenomKeeper struct { - denomMap map[string]common.Address - addrMap map[common.Address]string -} - -// GetContractAddrByDenom implements types.ERC20DenomKeeper. -func (e *MockERC20DenomKeeper) GetContractAddrByDenom(_ context.Context, denom string) (common.Address, error) { - addr, found := e.denomMap[denom] - if !found { - return common.Address{}, sdkerrors.ErrNotFound - } - - return addr, nil -} - -// GetDenomByContractAddr implements types.ERC20DenomKeeper. -func (e *MockERC20DenomKeeper) GetDenomByContractAddr(_ context.Context, addr common.Address) (string, error) { - denom, found := e.addrMap[addr] - if !found { - return "", sdkerrors.ErrNotFound - } - - return denom, nil -} diff --git a/x/evm/precompiles/erc20_registry/common_test.go b/x/evm/precompiles/erc20_registry/common_test.go new file mode 100644 index 0000000..dba0ab6 --- /dev/null +++ b/x/evm/precompiles/erc20_registry/common_test.go @@ -0,0 +1,246 @@ +package erc20registryprecompile_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/stateless" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie/utils" + "github.com/holiman/uint256" + + "github.com/initia-labs/minievm/x/evm/state" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var _ evmtypes.StateDB = &MockStateDB{} + +type MockStateDB struct { + ctx sdk.Context + initialCtx sdk.Context + + // Snapshot stack + snaps []*state.Snapshot +} + +func NewMockStateDB(ctx sdk.Context) *MockStateDB { + return &MockStateDB{ + ctx: ctx, + initialCtx: ctx, + } +} + +// Snapshot implements types.StateDB. +func (m *MockStateDB) Snapshot() int { + // get a current snapshot id + sid := len(m.snaps) - 1 + + // create a new snapshot + snap := state.NewSnapshot(m.ctx) + m.snaps = append(m.snaps, snap) + + // use the new snapshot context + m.ctx = snap.Context() + + // return the current snapshot id + return sid +} + +// RevertToSnapshot implements types.StateDB. +func (m *MockStateDB) RevertToSnapshot(i int) { + if i == -1 { + m.ctx = m.initialCtx + m.snaps = m.snaps[:0] + return + } + + // revert to the snapshot with the given id + snap := m.snaps[i] + m.ctx = snap.Context() + + // clear the snapshots after the given id + m.snaps = m.snaps[:i] +} + +// ContextOfSnapshot implements types.StateDB. +func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context { + if i == -1 { + return m.initialCtx + } + + return m.snaps[i].Context() +} + +//////////////////////// MOCKED METHODS //////////////////////// + +// AddAddressToAccessList implements types.StateDB. +func (m *MockStateDB) AddAddressToAccessList(addr common.Address) { + panic("unimplemented") +} + +// AddBalance implements types.StateDB. +func (m *MockStateDB) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) { + panic("unimplemented") +} + +// AddLog implements types.StateDB. +func (m *MockStateDB) AddLog(*types.Log) { + panic("unimplemented") +} + +// AddPreimage implements types.StateDB. +func (m *MockStateDB) AddPreimage(common.Hash, []byte) { + panic("unimplemented") +} + +// AddRefund implements types.StateDB. +func (m *MockStateDB) AddRefund(uint64) { + panic("unimplemented") +} + +// AddSlotToAccessList implements types.StateDB. +func (m *MockStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { + panic("unimplemented") +} + +// AddressInAccessList implements types.StateDB. +func (m *MockStateDB) AddressInAccessList(addr common.Address) bool { + panic("unimplemented") +} + +// CreateAccount implements types.StateDB. +func (m *MockStateDB) CreateAccount(common.Address) { + panic("unimplemented") +} + +// CreateContract implements types.StateDB. +func (m *MockStateDB) CreateContract(common.Address) { + panic("unimplemented") +} + +// Empty implements types.StateDB. +func (m *MockStateDB) Empty(common.Address) bool { + panic("unimplemented") +} + +// Exist implements types.StateDB. +func (m *MockStateDB) Exist(common.Address) bool { + panic("unimplemented") +} + +// GetBalance implements types.StateDB. +func (m *MockStateDB) GetBalance(common.Address) *uint256.Int { + panic("unimplemented") +} + +// GetCode implements types.StateDB. +func (m *MockStateDB) GetCode(common.Address) []byte { + panic("unimplemented") +} + +// GetCodeHash implements types.StateDB. +func (m *MockStateDB) GetCodeHash(common.Address) common.Hash { + panic("unimplemented") +} + +// GetCodeSize implements types.StateDB. +func (m *MockStateDB) GetCodeSize(common.Address) int { + panic("unimplemented") +} + +// GetCommittedState implements types.StateDB. +func (m *MockStateDB) GetCommittedState(common.Address, common.Hash) common.Hash { + panic("unimplemented") +} + +// GetNonce implements types.StateDB. +func (m *MockStateDB) GetNonce(common.Address) uint64 { + panic("unimplemented") +} + +// GetRefund implements types.StateDB. +func (m *MockStateDB) GetRefund() uint64 { + panic("unimplemented") +} + +// GetState implements types.StateDB. +func (m *MockStateDB) GetState(common.Address, common.Hash) common.Hash { + panic("unimplemented") +} + +// GetStorageRoot implements types.StateDB. +func (m *MockStateDB) GetStorageRoot(addr common.Address) common.Hash { + panic("unimplemented") +} + +// GetTransientState implements types.StateDB. +func (m *MockStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { + panic("unimplemented") +} + +// HasSelfDestructed implements types.StateDB. +func (m *MockStateDB) HasSelfDestructed(common.Address) bool { + panic("unimplemented") +} + +// PointCache implements types.StateDB. +func (m *MockStateDB) PointCache() *utils.PointCache { + panic("unimplemented") +} + +// Prepare implements types.StateDB. +func (m *MockStateDB) Prepare(rules params.Rules, sender common.Address, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) { + panic("unimplemented") +} + +// SelfDestruct implements types.StateDB. +func (m *MockStateDB) SelfDestruct(common.Address) { + panic("unimplemented") +} + +// Selfdestruct6780 implements types.StateDB. +func (m *MockStateDB) Selfdestruct6780(common.Address) { + panic("unimplemented") +} + +// SetCode implements types.StateDB. +func (m *MockStateDB) SetCode(common.Address, []byte) { + panic("unimplemented") +} + +// SetNonce implements types.StateDB. +func (m *MockStateDB) SetNonce(common.Address, uint64) { + panic("unimplemented") +} + +// SetState implements types.StateDB. +func (m *MockStateDB) SetState(common.Address, common.Hash, common.Hash) { + panic("unimplemented") +} + +// SetTransientState implements types.StateDB. +func (m *MockStateDB) SetTransientState(addr common.Address, key common.Hash, value common.Hash) { + panic("unimplemented") +} + +// SlotInAccessList implements types.StateDB. +func (m *MockStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { + panic("unimplemented") +} + +// SubBalance implements types.StateDB. +func (m *MockStateDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) { + panic("unimplemented") +} + +// SubRefund implements types.StateDB. +func (m *MockStateDB) SubRefund(uint64) { + panic("unimplemented") +} + +// Witness implements types.StateDB. +func (m *MockStateDB) Witness() *stateless.Witness { + panic("unimplemented") +} diff --git a/x/evm/precompiles/erc20_registry/contract.go b/x/evm/precompiles/erc20_registry/contract.go index 593b7ea..3e2739b 100644 --- a/x/evm/precompiles/erc20_registry/contract.go +++ b/x/evm/precompiles/erc20_registry/contract.go @@ -1,14 +1,12 @@ package erc20registryprecompile import ( - "context" "errors" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/vm" storetypes "cosmossdk.io/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/initia-labs/minievm/x/evm/contracts/i_erc20_registry" "github.com/initia-labs/minievm/x/evm/types" @@ -16,12 +14,12 @@ import ( var _ vm.ExtendedPrecompiledContract = ERC20RegistryPrecompile{} var _ vm.PrecompiledContract = ERC20RegistryPrecompile{} -var _ types.WithContext = ERC20RegistryPrecompile{} +var _ types.WithStateDB = ERC20RegistryPrecompile{} type ERC20RegistryPrecompile struct { *abi.ABI - ctx context.Context - k types.IERC20StoresKeeper + stateDB types.StateDB + k types.IERC20StoresKeeper } func NewERC20RegistryPrecompile(k types.IERC20StoresKeeper) (ERC20RegistryPrecompile, error) { @@ -33,8 +31,8 @@ func NewERC20RegistryPrecompile(k types.IERC20StoresKeeper) (ERC20RegistryPrecom return ERC20RegistryPrecompile{ABI: abi, k: k}, nil } -func (e ERC20RegistryPrecompile) WithContext(ctx context.Context) vm.PrecompiledContract { - e.ctx = ctx +func (e ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract { + e.stateDB = stateDB return e } @@ -47,17 +45,24 @@ const ( // ExtendedRun implements vm.ExtendedPrecompiledContract. func (e ERC20RegistryPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppliedGas uint64, readOnly bool) (resBz []byte, usedGas uint64, err error) { + snapshot := e.stateDB.Snapshot() + ctx := e.stateDB.ContextOfSnapshot(snapshot).WithGasMeter(storetypes.NewGasMeter(suppliedGas)) + defer func() { if r := recover(); r != nil { switch r.(type) { case storetypes.ErrorOutOfGas: // convert cosmos out of gas error to EVM out of gas error - usedGas = suppliedGas + 1 - err = nil + usedGas = suppliedGas + err = vm.ErrOutOfGas default: panic(r) } } + + if err != nil { + e.stateDB.RevertToSnapshot(snapshot) + } }() method, err := e.ABI.MethodById(input) @@ -70,7 +75,6 @@ func (e ERC20RegistryPrecompile) ExtendedRun(caller vm.ContractRef, input []byte return nil, 0, types.ErrPrecompileFailed.Wrap(err.Error()) } - ctx := sdk.UnwrapSDKContext(e.ctx).WithGasMeter(storetypes.NewGasMeter(suppliedGas)) ctx.GasMeter().ConsumeGas(storetypes.Gas(len(input))*GAS_PER_BYTE, "input bytes") switch method.Name { diff --git a/x/evm/precompiles/erc20_registry/contract_test.go b/x/evm/precompiles/erc20_registry/contract_test.go index 528fd5a..d7494f9 100644 --- a/x/evm/precompiles/erc20_registry/contract_test.go +++ b/x/evm/precompiles/erc20_registry/contract_test.go @@ -75,7 +75,8 @@ func Test_ERC20RegistryPrecompile(t *testing.T) { require.NoError(t, err) // set context - registry = registry.WithContext(ctx).(precompiles.ERC20RegistryPrecompile) + stateDB := NewMockStateDB(ctx) + registry = registry.WithStateDB(stateDB).(precompiles.ERC20RegistryPrecompile) erc20Addr := common.HexToAddress("0x1") accountAddr := common.HexToAddress("0x2") @@ -89,9 +90,8 @@ func Test_ERC20RegistryPrecompile(t *testing.T) { require.NoError(t, err) // out of gas error - _, gasUsed, err := registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_GAS-1, false) - require.NoError(t, err) - require.Equal(t, gasUsed, uint64(precompiles.REGISTER_GAS)) + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_GAS-1, false) + require.ErrorIs(t, err, vm.ErrOutOfGas) // non read only method fail _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_GAS+uint64(len(bz)), true) @@ -107,9 +107,8 @@ func Test_ERC20RegistryPrecompile(t *testing.T) { require.NoError(t, err) // out of gas error - _, gasUsed, err = registry.ExtendedRun(vm.AccountRef(erc20FactoryAddr), bz, precompiles.REGISTER_FROM_FACTORY_GAS-1, false) - require.NoError(t, err) - require.Equal(t, gasUsed, uint64(precompiles.REGISTER_FROM_FACTORY_GAS)) + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20FactoryAddr), bz, precompiles.REGISTER_FROM_FACTORY_GAS-1, false) + require.ErrorIs(t, err, vm.ErrOutOfGas) // non read only method fail _, _, err = registry.ExtendedRun(vm.AccountRef(erc20FactoryAddr), bz, precompiles.REGISTER_FROM_FACTORY_GAS+uint64(len(bz)), true) @@ -140,9 +139,8 @@ func Test_ERC20RegistryPrecompile(t *testing.T) { require.NoError(t, err) // out of gas error - _, gasUsed, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_STORE_GAS-1, false) - require.NoError(t, err) - require.Equal(t, gasUsed, uint64(precompiles.REGISTER_STORE_GAS)) + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_STORE_GAS-1, false) + require.ErrorIs(t, err, vm.ErrOutOfGas) // non read only method fail _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_STORE_GAS+uint64(len(bz)), true) @@ -158,9 +156,8 @@ func Test_ERC20RegistryPrecompile(t *testing.T) { require.NoError(t, err) // out of gas panic - _, gasUsed, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.IS_STORE_REGISTERED_GAS-1, true) - require.NoError(t, err) - require.Equal(t, gasUsed, uint64(precompiles.IS_STORE_REGISTERED_GAS)) + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.IS_STORE_REGISTERED_GAS-1, true) + require.ErrorIs(t, err, vm.ErrOutOfGas) resBz, usedGas, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.IS_STORE_REGISTERED_GAS+uint64(len(bz)), true) require.NoError(t, err) diff --git a/x/evm/state/snapshot.go b/x/evm/state/snapshot.go index de8f266..bed936e 100644 --- a/x/evm/state/snapshot.go +++ b/x/evm/state/snapshot.go @@ -23,3 +23,7 @@ func NewSnapshot(ctx context.Context) *Snapshot { func (s *Snapshot) Commit() { s.commit() } + +func (s *Snapshot) Context() sdk.Context { + return s.ctx +} diff --git a/x/evm/state/statedb.go b/x/evm/state/statedb.go index 4eb7926..682f4b6 100644 --- a/x/evm/state/statedb.go +++ b/x/evm/state/statedb.go @@ -589,6 +589,14 @@ func (s *StateDB) RevertToSnapshot(i int) { s.snaps = s.snaps[:i] } +func (s *StateDB) ContextOfSnapshot(i int) sdk.Context { + if i == -1 { + return s.initialCtx + } + + return s.snaps[i].ctx +} + // Prepare handles the preparatory steps for executing a state transition with. // This method must be invoked before state transition. // diff --git a/x/evm/types/expected_keeper.go b/x/evm/types/expected_keeper.go index 0bcbba5..6546333 100644 --- a/x/evm/types/expected_keeper.go +++ b/x/evm/types/expected_keeper.go @@ -85,8 +85,13 @@ type IERC721Keeper interface { GetTokenInfos(ctx context.Context, classId string, tokenIds []string) (tokenUris []string, tokenData []string, err error) } -type WithContext interface { - WithContext(ctx context.Context) vm.PrecompiledContract +type StateDB interface { + vm.StateDB + ContextOfSnapshot(i int) sdk.Context +} + +type WithStateDB interface { + WithStateDB(stateDB StateDB) vm.PrecompiledContract } type GRPCRouter interface {