diff --git a/app/ibc-hooks/README.md b/app/ibc-hooks/README.md index daffc3e..a355b33 100644 --- a/app/ibc-hooks/README.md +++ b/app/ibc-hooks/README.md @@ -2,7 +2,7 @@ This module is copied from [osmosis](https://github.com/osmosis-labs/osmosis) and changed to execute evm contract with ICS-20 token transfer calls. -## Move Hooks +## EVM Hooks The evm hook is an IBC middleware which is used to allow ICS-20 token transfers to initiate contract calls. This allows cross-chain contract calls, that involve token movement. @@ -12,7 +12,7 @@ One of primary importance is cross-chain swaps, which is an extremely powerful p The mechanism enabling this is a `memo` field on every ICS20 and ICS721 transfer packet as of [IBC v3.4.0](https://medium.com/the-interchain-foundation/moving-beyond-simple-token-transfers-d42b2b1dc29b). Move hooks is an IBC middleware that parses an ICS20 transfer, and if the `memo` field is of a particular form, executes a evm contract call. We now detail the `memo` format for `evm` contract calls, and the execution guarantees provided. -### Move Contract Execution Format +### EVM Contract Execution Format Before we dive into the IBC metadata format, we show the hook data format, so the reader has a sense of what are the fields we need to be setting in. The evm `MsgCall` is defined [here](../../x/evm/types/tx.pb.go) and other types are defined [here](./message.go) as the following type: @@ -48,6 +48,18 @@ type MsgCall struct { ContractAddr string `protobuf:"bytes,2,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` // Hex encoded execution input bytes. Input string `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` + // Value is the amount of fee denom token to transfer to the contract. + Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` + // AccessList is a predefined list of Ethereum addresses and their corresponding storage slots that a transaction will interact with during its execution. can be none + AccessList []AccessTuple `protobuf:"bytes,5,rep,name=access_list,json=accessList,proto3" json:"access_list"` +} + +type AccessTuple struct { + // Address of the contract that will be accessed during the transaction execution. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // A list of storage keys that the transaction will interact with within the specified contract. + // These keys represent specific storage slots in the contract's storage that are accessed or modified. + StorageKeys []string `protobuf:"bytes,2,rep,name=storage_keys,json=storageKeys,proto3" json:"storage_keys,omitempty"` } ``` @@ -71,6 +83,10 @@ msg := MsgCall{ ContractAddr: packet.data.memo["evm"]["message"]["contract_addr"], // Hex encoded execution input bytes. Input: packet.data.memo["evm"]["message"]["input"], + // Value is the amount of fee denom token to transfer to the contract. + Value: packet.data.memo["evm"]["message"]["value"] + // Value is the amount of fee denom token to transfer to the contract. + AccessList: packet.data.memo["evm"]["message"]["access_list"] } ``` @@ -93,6 +109,11 @@ ICS20 is JSON native, so we use JSON for the memo format. "message": { "contract_addr": "0x1", "input": "hex encoded byte string", + "value": "0", + "access_list": { + "address" : "0x1", // contract address + "storage_keys": ["0xabc","0xdef"] // storage keys of contract + } }, // optional field to get async callback (ack and timeout) "async_callback": { @@ -103,7 +124,6 @@ ICS20 is JSON native, so we use JSON for the memo format. } } } - ``` An ICS20 packet is formatted correctly for evmhooks iff the following all hold: @@ -111,7 +131,7 @@ An ICS20 packet is formatted correctly for evmhooks iff the following all hold: - `memo` is not blank - `memo` is valid JSON - `memo` has at least one key, with value `"evm"` -- `memo["evm"]["message"]` has exactly five entries, `"contract_addr"` and `"input"` +- `memo["evm"]["message"]` has exactly 4 entries, `"contract_addr"`, `"input"`, `"value"`, `"access_list"` - `receiver` == "" || `receiver` == "module_address::module_name::function_name" We consider an ICS20 packet as directed towards evmhooks iff all of the following hold: @@ -160,5 +180,39 @@ interface IIBCAsyncCallback { Also when a contract make IBC transfer request, it should provide async callback data through memo field. -- `memo['evm']['async_callback']['id']`: the async callback id is assigned from the contract. so later it will be passed as argument of `ibc_ack` and `ibc_timeout`. -- `memo['evm']['async_callback']['contract_addr']`: The address of module which defines the callback function. +- `memo['evm']['async_callback']['id']`: the async callback id is assigned from the contract. so later it will be passed as argument of `ibc_ack` and `ibc_timeout`. +- `memo['evm']['async_callback']['contract_addr']`: The address of contract which defines the callback function. + +### IBC Transfer using ERC20Wrapper + +`src -> dst`: Execute the ERC20Wrapper contract to wrap and do ibc-transfer + +`dst -> src`: ibc-trasfer and execute the ERC20Wrapper contract via ibc-hook + +- data example + +```json +{ + //... other ibc fields that we don't care about + "data": { + "denom": "wrapped token denom", // will be transformed to the local denom (ibc/...) + "amount": "1000", + "sender": "addr on counterparty chain", // will be transformed + "receiver": "0xcontractaddr", + "memo": { + "evm": { + // execute message on receive packet + "message": { + "contract_addr": "0xerc20_wrapper_contract", // should query erc20 wrapper contract addr + "input": "pack(unwrap, denom, recipient, amount)", // function selector(fc078758) + abiCoder.encode([string,address,address],denom,recipient,amount) ref) https://docs.ethers.org/v6/api/abi/abi-coder/#AbiCoder-encode + "value": "0", + "access_list": { + "address" : "...", // contract address + "storage_keys": ["...","..."] // storage keys of contract + } + } + } + } + } +} +``` diff --git a/proto/minievm/evm/v1/genesis.proto b/proto/minievm/evm/v1/genesis.proto index e70eff6..f9718bf 100644 --- a/proto/minievm/evm/v1/genesis.proto +++ b/proto/minievm/evm/v1/genesis.proto @@ -47,6 +47,9 @@ message GenesisState { // erc20 factory contract address bytes erc20_factory = 8; + + // erc20 wrapper contract address + bytes erc20_wrapper = 9; } // GenesisKeyValue defines store KV values. diff --git a/proto/minievm/evm/v1/query.proto b/proto/minievm/evm/v1/query.proto index 3899c91..f199509 100644 --- a/proto/minievm/evm/v1/query.proto +++ b/proto/minievm/evm/v1/query.proto @@ -27,6 +27,11 @@ service Query { option (google.api.http).get = "/minievm/evm/v1/contracts/erc20_factory"; } + // ERC20Wrapper gets the ERC20Wrapper contract address. + rpc ERC20Wrapper(QueryERC20WrapperRequest) returns (QueryERC20WrapperResponse) { + option (google.api.http).get = "/minievm/evm/v1/contracts/erc20_wrapper"; + } + // ContractAddrByDenom gets the contract address by denom. rpc ContractAddrByDenom(QueryContractAddrByDenomRequest) returns (QueryContractAddrByDenomResponse) { option (google.api.http).get = "/minievm/evm/v1/contracts/by_denom"; @@ -94,6 +99,18 @@ message QueryERC20FactoryResponse { string address = 1; } +// QueryERC20WrapperRequest is the request type for the Query/ERC20Wrapper RPC +// method +message QueryERC20WrapperRequest {} + +// QueryERC20WrapperResponse is the response type for the Query/ERC20Wrapper RPC +// method +message QueryERC20WrapperResponse { + option (gogoproto.equal) = true; + // 0x prefixed hex address + string address = 1; +} + // QueryContractAddrByDenomRequest is the request type for the Query/ContractAddrByDenom RPC // method message QueryContractAddrByDenomRequest { diff --git a/x/evm/contracts/erc20_wrapper/ERC20Wrapper.go b/x/evm/contracts/erc20_wrapper/ERC20Wrapper.go new file mode 100644 index 0000000..002de85 --- /dev/null +++ b/x/evm/contracts/erc20_wrapper/ERC20Wrapper.go @@ -0,0 +1,790 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc20_wrapper + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// Erc20WrapperMetaData contains all meta data concerning the Erc20Wrapper contract. +var Erc20WrapperMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"erc20Factory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"StringsInsufficientHexLength\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"erc20\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"name\":\"createERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"contractERC20Factory\",\"name\":\"\",\"type\":\"address\"}],\"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\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"originTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"wrappedTokenDenom\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wrappedAmt\",\"type\":\"uint256\"}],\"name\":\"unwrap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"channel\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"receiver\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timeout\",\"type\":\"uint256\"}],\"name\":\"wrap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"wrappedTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040525f8060146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550348015610037575f80fd5b5060405161520e38038061520e83398181016040528101906100599190610130565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505061015b565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100ff826100d6565b9050919050565b61010f816100f5565b8114610119575f80fd5b50565b5f8151905061012a81610106565b92915050565b5f60208284031215610145576101446100d2565b5b5f6101528482850161011c565b91505092915050565b60805161509461017a5f395f8181610935015261101501526150945ff3fe608060405234801561000f575f80fd5b50600436106100a7575f3560e01c80639a1114321161006f5780639a11143214610161578063b5ad1fb61461017d578063c45a0155146101ad578063d5c6b504146101cb578063f2fde38b146101fb578063fc07875814610217576100a7565b806301ffc9a7146100ab57806306ef1a86146100db5780630d4f1f9d1461010b57806331a503f0146101275780638da5cb5b14610143575b5f80fd5b6100c560048036038101906100c09190611a72565b610233565b6040516100d29190611ab7565b60405180910390f35b6100f560048036038101906100f09190611c42565b61029c565b6040516101029190611d09565b60405180910390f35b61012560048036038101906101209190611d89565b61041b565b005b610141600480360381019061013c9190611dc7565b61042e565b005b61014b61043a565b6040516101589190611d09565b60405180910390f35b61017b60048036038101906101769190611e4f565b61045d565b005b61019760048036038101906101929190611efe565b610903565b6040516101a49190611d09565b60405180910390f35b6101b5610933565b6040516101c29190611f84565b60405180910390f35b6101e560048036038101906101e09190611efe565b610957565b6040516101f29190611d09565b60405180910390f35b61021560048036038101906102109190611efe565b610987565b005b610231600480360381019061022c9190611f9d565b610acf565b005b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f808484846040516102ad906119ff565b6102b993929190612078565b604051809103905ff0801580156102d2573d5f803e3d5ffd5b50905060f273ffffffffffffffffffffffffffffffffffffffff1663d126274a826040518263ffffffff1660e01b815260040161030f9190611d09565b6020604051808303815f875af115801561032b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061034f91906120cf565b508073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b336040518263ffffffff1660e01b81526004016103899190611d09565b5f604051808303815f87803b1580156103a0575f80fd5b505af11580156103b2573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d160405160405180910390a3809150509392505050565b8061042a5761042982610e48565b5b5050565b61043781610e48565b50565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61046684610f83565b8373ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b81526004016104a393929190612109565b6020604051808303815f875af11580156104bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e391906120cf565b505f61055d838673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610532573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105569190612152565b6006611338565b905060015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f1930836040518363ffffffff1660e01b81526004016105f692919061217d565b5f604051808303815f87803b15801561060d575f80fd5b505af115801561061f573d5f803e3d5ffd5b5050505060015f60148282829054906101000a900467ffffffffffffffff1661064891906121d1565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060405180606001604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160f173ffffffffffffffffffffffffffffffffffffffff166381cf0f6a60015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b815260040161072b9190611d09565b5f604051808303815f875af1158015610746573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061076e919061227a565b81526020018281525060035f8060149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101908161080a91906124b2565b506040820151816002015590505060f173ffffffffffffffffffffffffffffffffffffffff1663d46f64e661089e8860015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685878a611407565b6040518263ffffffff1660e01b81526004016108ba9190612581565b6020604051808303815f875af11580156108d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108fa91906120cf565b50505050505050565b6002602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109dd575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610a14575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f60f173ffffffffffffffffffffffffffffffffffffffff16632b3324ce856040518263ffffffff1660e01b8152600401610b0a9190612581565b6020604051808303815f875af1158015610b26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4a91906125b5565b90505f73ffffffffffffffffffffffffffffffffffffffff1660025f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610c16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0d9061262a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166379cc679033846040518363ffffffff1660e01b8152600401610c5192919061217d565b6020604051808303815f875af1158015610c6d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9191906120cf565b505f610d6783600660025f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d629190612152565b611338565b905060025f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836040518363ffffffff1660e01b8152600401610e0092919061217d565b6020604051808303815f875af1158015610e1c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4091906120cf565b505050505050565b5f60035f8367ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f206040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182018054610edd906122ee565b80601f0160208091040260200160405190810160405280929190818152602001828054610f09906122ee565b8015610f545780601f10610f2b57610100808354040283529160200191610f54565b820191905f5260205f20905b815481529060010190602001808311610f3757829003601f168201915b505050505081526020016002820154815250509050610f7f8160200151825f01518360400151610acf565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff1660015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611335575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166306ef1a866040518060400160405280600781526020017f57726170706564000000000000000000000000000000000000000000000000008152508473ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa1580156110cd573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906110f5919061227a565b604051602001611106929190612682565b6040516020818303038152906040526040518060400160405280600181526020017f57000000000000000000000000000000000000000000000000000000000000008152508573ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa158015611193573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906111bb919061227a565b6040516020016111cc929190612682565b60405160208183030381529060405260066040518463ffffffff1660e01b81526004016111fb93929190612078565b6020604051808303815f875af1158015611217573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123b91906125b5565b90508060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160025f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b50565b5f8160ff168360ff161115611379575f828461135491906126a5565b60ff16600a6113639190612808565b90508085611371919061287f565b9150506113be565b8160ff168360ff1610156113b9575f838361139491906126a5565b60ff16600a6113a39190612808565b905080856113b191906128af565b9150506113bd565b8390505b5b5f8103611400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f79061293a565b60405180910390fd5b9392505050565b60608560f173ffffffffffffffffffffffffffffffffffffffff166381cf0f6a876040518263ffffffff1660e01b81526004016114449190611d09565b5f604051808303815f875af115801561145f573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611487919061227a565b61149086611579565b60f173ffffffffffffffffffffffffffffffffffffffff16636af32a55306040518263ffffffff1660e01b81526004016114ca9190611d09565b5f604051808303815f875af11580156114e5573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061150d919061227a565b8561151788611579565b61153f5f60149054906101000a900467ffffffffffffffff1667ffffffffffffffff16611579565b61154830611643565b60405160200161155f989796959493929190612e20565b604051602081830303815290604052905095945050505050565b60605f600161158784611670565b0190505f8167ffffffffffffffff8111156115a5576115a4611ae8565b5b6040519080825280601f01601f1916602001820160405280156115d75781602001600182028036833780820191505090505b5090505f82602001820190505b600115611638578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161162d5761162c612852565b5b0494505f85036115e4575b819350505050919050565b60606116698273ffffffffffffffffffffffffffffffffffffffff16601460ff166117c1565b9050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106116cc577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816116c2576116c1612852565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611709576d04ee2d6d415b85acef810000000083816116ff576116fe612852565b5b0492506020810190505b662386f26fc10000831061173857662386f26fc10000838161172e5761172d612852565b5b0492506010810190505b6305f5e1008310611761576305f5e100838161175757611756612852565b5b0492506008810190505b612710831061178657612710838161177c5761177b612852565b5b0492506004810190505b606483106117a9576064838161179f5761179e612852565b5b0492506002810190505b600a83106117b8576001810190505b80915050919050565b60605f8390505f60028460026117d791906128af565b6117e19190612f6d565b67ffffffffffffffff8111156117fa576117f9611ae8565b5b6040519080825280601f01601f19166020018201604052801561182c5781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f8151811061186357611862612fa0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106118c6576118c5612fa0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600185600261190491906128af565b61190e9190612f6d565b90505b60018111156119ad577f3031323334353637383961626364656600000000000000000000000000000000600f8416601081106119505761194f612fa0565b5b1a60f81b82828151811061196757611966612fa0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600483901c9250806119a690612fcd565b9050611911565b505f82146119f45784846040517fe22e27eb0000000000000000000000000000000000000000000000000000000081526004016119eb929190612ff4565b60405180910390fd5b809250505092915050565b6120438061301c83390190565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611a5181611a1d565b8114611a5b575f80fd5b50565b5f81359050611a6c81611a48565b92915050565b5f60208284031215611a8757611a86611a15565b5b5f611a9484828501611a5e565b91505092915050565b5f8115159050919050565b611ab181611a9d565b82525050565b5f602082019050611aca5f830184611aa8565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611b1e82611ad8565b810181811067ffffffffffffffff82111715611b3d57611b3c611ae8565b5b80604052505050565b5f611b4f611a0c565b9050611b5b8282611b15565b919050565b5f67ffffffffffffffff821115611b7a57611b79611ae8565b5b611b8382611ad8565b9050602081019050919050565b828183375f83830152505050565b5f611bb0611bab84611b60565b611b46565b905082815260208101848484011115611bcc57611bcb611ad4565b5b611bd7848285611b90565b509392505050565b5f82601f830112611bf357611bf2611ad0565b5b8135611c03848260208601611b9e565b91505092915050565b5f60ff82169050919050565b611c2181611c0c565b8114611c2b575f80fd5b50565b5f81359050611c3c81611c18565b92915050565b5f805f60608486031215611c5957611c58611a15565b5b5f84013567ffffffffffffffff811115611c7657611c75611a19565b5b611c8286828701611bdf565b935050602084013567ffffffffffffffff811115611ca357611ca2611a19565b5b611caf86828701611bdf565b9250506040611cc086828701611c2e565b9150509250925092565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611cf382611cca565b9050919050565b611d0381611ce9565b82525050565b5f602082019050611d1c5f830184611cfa565b92915050565b5f67ffffffffffffffff82169050919050565b611d3e81611d22565b8114611d48575f80fd5b50565b5f81359050611d5981611d35565b92915050565b611d6881611a9d565b8114611d72575f80fd5b50565b5f81359050611d8381611d5f565b92915050565b5f8060408385031215611d9f57611d9e611a15565b5b5f611dac85828601611d4b565b9250506020611dbd85828601611d75565b9150509250929050565b5f60208284031215611ddc57611ddb611a15565b5b5f611de984828501611d4b565b91505092915050565b611dfb81611ce9565b8114611e05575f80fd5b50565b5f81359050611e1681611df2565b92915050565b5f819050919050565b611e2e81611e1c565b8114611e38575f80fd5b50565b5f81359050611e4981611e25565b92915050565b5f805f805f60a08688031215611e6857611e67611a15565b5b5f86013567ffffffffffffffff811115611e8557611e84611a19565b5b611e9188828901611bdf565b9550506020611ea288828901611e08565b945050604086013567ffffffffffffffff811115611ec357611ec2611a19565b5b611ecf88828901611bdf565b9350506060611ee088828901611e3b565b9250506080611ef188828901611e3b565b9150509295509295909350565b5f60208284031215611f1357611f12611a15565b5b5f611f2084828501611e08565b91505092915050565b5f819050919050565b5f611f4c611f47611f4284611cca565b611f29565b611cca565b9050919050565b5f611f5d82611f32565b9050919050565b5f611f6e82611f53565b9050919050565b611f7e81611f64565b82525050565b5f602082019050611f975f830184611f75565b92915050565b5f805f60608486031215611fb457611fb3611a15565b5b5f84013567ffffffffffffffff811115611fd157611fd0611a19565b5b611fdd86828701611bdf565b9350506020611fee86828701611e08565b9250506040611fff86828701611e3b565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f61203b82612009565b6120458185612013565b9350612055818560208601612023565b61205e81611ad8565b840191505092915050565b61207281611c0c565b82525050565b5f6060820190508181035f8301526120908186612031565b905081810360208301526120a48185612031565b90506120b36040830184612069565b949350505050565b5f815190506120c981611d5f565b92915050565b5f602082840312156120e4576120e3611a15565b5b5f6120f1848285016120bb565b91505092915050565b61210381611e1c565b82525050565b5f60608201905061211c5f830186611cfa565b6121296020830185611cfa565b61213660408301846120fa565b949350505050565b5f8151905061214c81611c18565b92915050565b5f6020828403121561216757612166611a15565b5b5f6121748482850161213e565b91505092915050565b5f6040820190506121905f830185611cfa565b61219d60208301846120fa565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6121db82611d22565b91506121e683611d22565b9250828201905067ffffffffffffffff811115612206576122056121a4565b5b92915050565b5f61221e61221984611b60565b611b46565b90508281526020810184848401111561223a57612239611ad4565b5b612245848285612023565b509392505050565b5f82601f83011261226157612260611ad0565b5b815161227184826020860161220c565b91505092915050565b5f6020828403121561228f5761228e611a15565b5b5f82015167ffffffffffffffff8111156122ac576122ab611a19565b5b6122b88482850161224d565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061230557607f821691505b602082108103612318576123176122c1565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261237a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261233f565b612384868361233f565b95508019841693508086168417925050509392505050565b5f6123b66123b16123ac84611e1c565b611f29565b611e1c565b9050919050565b5f819050919050565b6123cf8361239c565b6123e36123db826123bd565b84845461234b565b825550505050565b5f90565b6123f76123eb565b6124028184846123c6565b505050565b5b818110156124255761241a5f826123ef565b600181019050612408565b5050565b601f82111561246a5761243b8161231e565b61244484612330565b81016020851015612453578190505b61246761245f85612330565b830182612407565b50505b505050565b5f82821c905092915050565b5f61248a5f198460080261246f565b1980831691505092915050565b5f6124a2838361247b565b9150826002028217905092915050565b6124bb82612009565b67ffffffffffffffff8111156124d4576124d3611ae8565b5b6124de82546122ee565b6124e9828285612429565b5f60209050601f83116001811461251a575f8415612508578287015190505b6125128582612497565b865550612579565b601f1984166125288661231e565b5f5b8281101561254f5784890151825560018201915060208501945060208101905061252a565b8683101561256c5784890151612568601f89168261247b565b8355505b6001600288020188555050505b505050505050565b5f6020820190508181035f8301526125998184612031565b905092915050565b5f815190506125af81611df2565b92915050565b5f602082840312156125ca576125c9611a15565b5b5f6125d7848285016125a1565b91505092915050565b7f6f726967696e20746f6b656e20646f65736e27742065786973740000000000005f82015250565b5f612614601a83612013565b915061261f826125e0565b602082019050919050565b5f6020820190508181035f83015261264181612608565b9050919050565b5f81905092915050565b5f61265c82612009565b6126668185612648565b9350612676818560208601612023565b80840191505092915050565b5f61268d8285612652565b91506126998284612652565b91508190509392505050565b5f6126af82611c0c565b91506126ba83611c0c565b9250828203905060ff8111156126d3576126d26121a4565b5b92915050565b5f8160011c9050919050565b5f808291508390505b600185111561272e5780860481111561270a576127096121a4565b5b60018516156127195780820291505b8081029050612727856126d9565b94506126ee565b94509492505050565b5f826127465760019050612801565b81612753575f9050612801565b81600181146127695760028114612773576127a2565b6001915050612801565b60ff841115612785576127846121a4565b5b8360020a91508482111561279c5761279b6121a4565b5b50612801565b5060208310610133831016604e8410600b84101617156127d75782820a9050838111156127d2576127d16121a4565b5b612801565b6127e484848460016126e5565b925090508184048111156127fb576127fa6121a4565b5b81810290505b9392505050565b5f61281282611e1c565b915061281d83611e1c565b925061284a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612737565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61288982611e1c565b915061289483611e1c565b9250826128a4576128a3612852565b5b828204905092915050565b5f6128b982611e1c565b91506128c483611e1c565b92508282026128d281611e1c565b915082820484148315176128e9576128e86121a4565b5b5092915050565b7f636f6e76657274656420616d6f756e74206973207a65726f00000000000000005f82015250565b5f612924601883612013565b915061292f826128f0565b602082019050919050565b5f6020820190508181035f83015261295181612918565b9050919050565b7f7b224074797065223a20222f6962632e6170706c69636174696f6e732e7472615f8201527f6e736665722e76312e4d73675472616e73666572222c00000000000000000000602082015250565b5f6129b2603683612648565b91506129bd82612958565b603682019050919050565b7f22736f757263655f706f7274223a20227472616e73666572222c0000000000005f82015250565b5f6129fc601a83612648565b9150612a07826129c8565b601a82019050919050565b7f22736f757263655f6368616e6e656c223a2022000000000000000000000000005f82015250565b5f612a46601383612648565b9150612a5182612a12565b601382019050919050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f612a90600283612648565b9150612a9b82612a5c565b600282019050919050565b7f22746f6b656e223a207b202264656e6f6d223a202200000000000000000000005f82015250565b5f612ada601583612648565b9150612ae582612aa6565b601582019050919050565b7f22616d6f756e74223a20220000000000000000000000000000000000000000005f82015250565b5f612b24600b83612648565b9150612b2f82612af0565b600b82019050919050565b7f227d2c00000000000000000000000000000000000000000000000000000000005f82015250565b5f612b6e600383612648565b9150612b7982612b3a565b600382019050919050565b7f2273656e646572223a20220000000000000000000000000000000000000000005f82015250565b5f612bb8600b83612648565b9150612bc382612b84565b600b82019050919050565b7f227265636569766572223a2022000000000000000000000000000000000000005f82015250565b5f612c02600d83612648565b9150612c0d82612bce565b600d82019050919050565b7f2274696d656f75745f686569676874223a207b227265766973696f6e5f6e756d5f8201527f626572223a202230222c227265766973696f6e5f686569676874223a2022302260208201527f7d2c000000000000000000000000000000000000000000000000000000000000604082015250565b5f612c98604283612648565b9150612ca382612c18565b604282019050919050565b7f2274696d656f75745f74696d657374616d70223a2022000000000000000000005f82015250565b5f612ce2601683612648565b9150612ced82612cae565b601682019050919050565b7f226d656d6f223a2022222c0000000000000000000000000000000000000000005f82015250565b5f612d2c600b83612648565b9150612d3782612cf8565b600b82019050919050565b7f226173796e635f63616c6c6261636b223a207b226964223a20220000000000005f82015250565b5f612d76601a83612648565b9150612d8182612d42565b601a82019050919050565b7f22636f6e74726163745f61646472657373223a202200000000000000000000005f82015250565b5f612dc0601583612648565b9150612dcb82612d8c565b601582019050919050565b7f227d7d00000000000000000000000000000000000000000000000000000000005f82015250565b5f612e0a600383612648565b9150612e1582612dd6565b600382019050919050565b5f612e2a826129a6565b9150612e35826129f0565b9150612e4082612a3a565b9150612e4c828b612652565b9150612e5782612a84565b9150612e6282612ace565b9150612e6e828a612652565b9150612e7982612a84565b9150612e8482612b18565b9150612e908289612652565b9150612e9b82612b62565b9150612ea682612bac565b9150612eb28288612652565b9150612ebd82612a84565b9150612ec882612bf6565b9150612ed48287612652565b9150612edf82612a84565b9150612eea82612c8c565b9150612ef582612cd6565b9150612f018286612652565b9150612f0c82612a84565b9150612f1782612d20565b9150612f2282612d6a565b9150612f2e8285612652565b9150612f3982612a84565b9150612f4482612db4565b9150612f508284612652565b9150612f5b82612dfe565b91508190509998505050505050505050565b5f612f7782611e1c565b9150612f8283611e1c565b9250828201905080821115612f9a57612f996121a4565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612fd782611e1c565b91505f8203612fe957612fe86121a4565b5b600182039050919050565b5f6040820190506130075f8301856120fa565b61301460208301846120fa565b939250505056fe608060405234801561000f575f80fd5b5060405161204338038061204383398181016040528101906100319190610235565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003908161007f91906104ca565b50816004908161008f91906104ca565b508060055f6101000a81548160ff021916908360ff160217905550505050610599565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610111826100cb565b810181811067ffffffffffffffff821117156101305761012f6100db565b5b80604052505050565b5f6101426100b2565b905061014e8282610108565b919050565b5f67ffffffffffffffff82111561016d5761016c6100db565b5b610176826100cb565b9050602081019050919050565b8281835e5f83830152505050565b5f6101a361019e84610153565b610139565b9050828152602081018484840111156101bf576101be6100c7565b5b6101ca848285610183565b509392505050565b5f82601f8301126101e6576101e56100c3565b5b81516101f6848260208601610191565b91505092915050565b5f60ff82169050919050565b610214816101ff565b811461021e575f80fd5b50565b5f8151905061022f8161020b565b92915050565b5f805f6060848603121561024c5761024b6100bb565b5b5f84015167ffffffffffffffff811115610269576102686100bf565b5b610275868287016101d2565b935050602084015167ffffffffffffffff811115610296576102956100bf565b5b6102a2868287016101d2565b92505060406102b386828701610221565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061030b57607f821691505b60208210810361031e5761031d6102c7565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026103807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610345565b61038a8683610345565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6103ce6103c96103c4846103a2565b6103ab565b6103a2565b9050919050565b5f819050919050565b6103e7836103b4565b6103fb6103f3826103d5565b848454610351565b825550505050565b5f90565b61040f610403565b61041a8184846103de565b505050565b5b8181101561043d576104325f82610407565b600181019050610420565b5050565b601f8211156104825761045381610324565b61045c84610336565b8101602085101561046b578190505b61047f61047785610336565b83018261041f565b50505b505050565b5f82821c905092915050565b5f6104a25f1984600802610487565b1980831691505092915050565b5f6104ba8383610493565b9150826002028217905092915050565b6104d3826102bd565b67ffffffffffffffff8111156104ec576104eb6100db565b5b6104f682546102f4565b610501828285610441565b5f60209050601f831160018114610532575f8415610520578287015190505b61052a85826104af565b865550610591565b601f19841661054086610324565b5f5b8281101561056757848901518255600182019150602085019450602081019050610542565b868310156105845784890151610580601f891682610493565b8355505b6001600288020188555050505b505050505050565b611a9d806105a65f395ff3fe608060405234801561000f575f80fd5b5060043610610114575f3560e01c806342966c68116100a057806395d89b411161006f57806395d89b41146102f0578063a9059cbb1461030e578063dd62ed3e1461033e578063f2fde38b1461036e578063fe1195ec1461038a57610114565b806342966c681461025657806370a082311461027257806379cc6790146102a25780638da5cb5b146102d257610114565b80631988513b116100e75780631988513b146101b457806323b872dd146101d05780632d688ca814610200578063313ce5671461021c57806340c10f191461023a57610114565b806301ffc9a71461011857806306fdde0314610148578063095ea7b31461016657806318160ddd14610196575b5f80fd5b610132600480360381019061012d919061143b565b6103a6565b60405161013f9190611480565b60405180910390f35b61015061041f565b60405161015d9190611509565b60405180910390f35b610180600480360381019061017b91906115b6565b6104ab565b60405161018d9190611480565b60405180910390f35b61019e610598565b6040516101ab9190611603565b60405180910390f35b6101ce60048036038101906101c9919061161c565b61059e565b005b6101ea60048036038101906101e5919061161c565b61061d565b6040516101f79190611480565b60405180910390f35b61021a600480360381019061021591906115b6565b61077d565b005b6102246107fa565b6040516102319190611687565b60405180910390f35b610254600480360381019061024f91906115b6565b61080c565b005b610270600480360381019061026b91906116a0565b61092b565b005b61028c600480360381019061028791906116cb565b6109f3565b6040516102999190611603565b60405180910390f35b6102bc60048036038101906102b791906115b6565b610a08565b6040516102c99190611480565b60405180910390f35b6102da610b66565b6040516102e79190611705565b60405180910390f35b6102f8610b89565b6040516103059190611509565b60405180910390f35b610328600480360381019061032391906115b6565b610c15565b6040516103359190611480565b60405180910390f35b6103586004803603810190610353919061171e565b610ce6565b6040516103659190611603565b60405180910390f35b610388600480360381019061038391906116cb565b610d06565b005b6103a4600480360381019061039f91906115b6565b610e4e565b005b5f7f8da6da19000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610418575061041782610ecb565b5b9050919050565b6003805461042c90611789565b80601f016020809104026020016040519081016040528092919081815260200182805461045890611789565b80156104a35780601f1061047a576101008083540402835291602001916104a3565b820191905f5260205f20905b81548152906001019060200180831161048657829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516105869190611603565b60405180910390a36001905092915050565b60065481565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461060d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060490611803565b60405180910390fd5b610618838383610f34565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b81526004016106599190611705565b602060405180830381865afa158015610674573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610698919061184b565b156106d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106cf906118e6565b60405180910390fd5b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461075f9190611931565b92505081905550610771858585610f34565b60019150509392505050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107e390611803565b60405180910390fd5b6107f6828261113f565b5050565b60055f9054906101000a900460ff1681565b8160f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b81526004016108479190611705565b602060405180830381865afa158015610862573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610886919061184b565b156108c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108bd906119ae565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461091c575f80fd5b610926838361113f565b505050565b3360f173ffffffffffffffffffffffffffffffffffffffff166360dc402f826040518263ffffffff1660e01b81526004016109669190611705565b602060405180830381865afa158015610981573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a5919061184b565b156109e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109dc90611a16565b60405180910390fd5b6109ef338361130e565b5050565b6001602052805f5260405f205f915090505481565b5f8260f173ffffffffffffffffffffffffffffffffffffffff166360dc402f826040518263ffffffff1660e01b8152600401610a449190611705565b602060405180830381865afa158015610a5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a83919061184b565b15610ac3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aba90611a16565b60405180910390fd5b8260025f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610b4a9190611931565b92505081905550610b5b848461130e565b600191505092915050565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60048054610b9690611789565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc290611789565b8015610c0d5780601f10610be457610100808354040283529160200191610c0d565b820191905f5260205f20905b815481529060010190602001808311610bf057829003601f168201915b505050505081565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b8152600401610c519190611705565b602060405180830381865afa158015610c6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c90919061184b565b15610cd0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc7906118e6565b60405180910390fd5b610cdb338585610f34565b600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5c575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d93575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ebd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb490611803565b60405180910390fd5b610ec7828261130e565b5050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610f6f9190611705565b602060405180830381865afa158015610f8a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fae919061184b565b61102e5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610fec9190611705565b6020604051808303815f875af1158015611008573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102c919061184b565b505b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461107a9190611931565b925050819055508160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110cd9190611a34565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516111319190611603565b60405180910390a350505050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b815260040161117a9190611705565b602060405180830381865afa158015611195573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111b9919061184b565b6112395760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016111f79190611705565b6020604051808303815f875af1158015611213573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611237919061184b565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546112859190611a34565b925050819055508160065f82825461129d9190611a34565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516113019190611603565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461135a9190611931565b925050819055508060065f8282546113729190611931565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516113d69190611603565b60405180910390a35050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61141a816113e6565b8114611424575f80fd5b50565b5f8135905061143581611411565b92915050565b5f602082840312156114505761144f6113e2565b5b5f61145d84828501611427565b91505092915050565b5f8115159050919050565b61147a81611466565b82525050565b5f6020820190506114935f830184611471565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6114db82611499565b6114e581856114a3565b93506114f58185602086016114b3565b6114fe816114c1565b840191505092915050565b5f6020820190508181035f83015261152181846114d1565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61155282611529565b9050919050565b61156281611548565b811461156c575f80fd5b50565b5f8135905061157d81611559565b92915050565b5f819050919050565b61159581611583565b811461159f575f80fd5b50565b5f813590506115b08161158c565b92915050565b5f80604083850312156115cc576115cb6113e2565b5b5f6115d98582860161156f565b92505060206115ea858286016115a2565b9150509250929050565b6115fd81611583565b82525050565b5f6020820190506116165f8301846115f4565b92915050565b5f805f60608486031215611633576116326113e2565b5b5f6116408682870161156f565b93505060206116518682870161156f565b9250506040611662868287016115a2565b9150509250925092565b5f60ff82169050919050565b6116818161166c565b82525050565b5f60208201905061169a5f830184611678565b92915050565b5f602082840312156116b5576116b46113e2565b5b5f6116c2848285016115a2565b91505092915050565b5f602082840312156116e0576116df6113e2565b5b5f6116ed8482850161156f565b91505092915050565b6116ff81611548565b82525050565b5f6020820190506117185f8301846116f6565b92915050565b5f8060408385031215611734576117336113e2565b5b5f6117418582860161156f565b92505060206117528582860161156f565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806117a057607f821691505b6020821081036117b3576117b261175c565b5b50919050565b7f45524332303a2063616c6c6572206973206e6f742074686520636861696e00005f82015250565b5f6117ed601e836114a3565b91506117f8826117b9565b602082019050919050565b5f6020820190508181035f83015261181a816117e1565b9050919050565b61182a81611466565b8114611834575f80fd5b50565b5f8151905061184581611821565b92915050565b5f602082840312156118605761185f6113e2565b5b5f61186d84828501611837565b91505092915050565b7f45524332303a207472616e7366657220746f20626c6f636b65642061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f6118d06022836114a3565b91506118db82611876565b604082019050919050565b5f6020820190508181035f8301526118fd816118c4565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61193b82611583565b915061194683611583565b925082820390508181111561195e5761195d611904565b5b92915050565b7f45524332303a206d696e7420746f20626c6f636b6564206164647265737300005f82015250565b5f611998601e836114a3565b91506119a382611964565b602082019050919050565b5f6020820190508181035f8301526119c58161198c565b9050919050565b7f45524332303a206275726e2066726f6d206d6f64756c652061646472657373005f82015250565b5f611a00601f836114a3565b9150611a0b826119cc565b602082019050919050565b5f6020820190508181035f830152611a2d816119f4565b9050919050565b5f611a3e82611583565b9150611a4983611583565b9250828201905080821115611a6157611a60611904565b5b9291505056fea2646970667358221220de4043b1adb87162ffc06c0127fc335d705e04b467c9acd7522c8721ebd4c4bb64736f6c63430008190033a2646970667358221220b60b16dbb873bc70c6d83f4f9c9822c78b2d692f5c12918ad733994c055bb7b664736f6c63430008190033", +} + +// Erc20WrapperABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc20WrapperMetaData.ABI instead. +var Erc20WrapperABI = Erc20WrapperMetaData.ABI + +// Erc20WrapperBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use Erc20WrapperMetaData.Bin instead. +var Erc20WrapperBin = Erc20WrapperMetaData.Bin + +// DeployErc20Wrapper deploys a new Ethereum contract, binding an instance of Erc20Wrapper to it. +func DeployErc20Wrapper(auth *bind.TransactOpts, backend bind.ContractBackend, erc20Factory common.Address) (common.Address, *types.Transaction, *Erc20Wrapper, error) { + parsed, err := Erc20WrapperMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(Erc20WrapperBin), backend, erc20Factory) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Erc20Wrapper{Erc20WrapperCaller: Erc20WrapperCaller{contract: contract}, Erc20WrapperTransactor: Erc20WrapperTransactor{contract: contract}, Erc20WrapperFilterer: Erc20WrapperFilterer{contract: contract}}, nil +} + +// Erc20Wrapper is an auto generated Go binding around an Ethereum contract. +type Erc20Wrapper struct { + Erc20WrapperCaller // Read-only binding to the contract + Erc20WrapperTransactor // Write-only binding to the contract + Erc20WrapperFilterer // Log filterer for contract events +} + +// Erc20WrapperCaller is an auto generated read-only Go binding around an Ethereum contract. +type Erc20WrapperCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20WrapperTransactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc20WrapperTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20WrapperFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc20WrapperFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20WrapperSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc20WrapperSession struct { + Contract *Erc20Wrapper // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20WrapperCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc20WrapperCallerSession struct { + Contract *Erc20WrapperCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc20WrapperTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc20WrapperTransactorSession struct { + Contract *Erc20WrapperTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20WrapperRaw is an auto generated low-level Go binding around an Ethereum contract. +type Erc20WrapperRaw struct { + Contract *Erc20Wrapper // Generic contract binding to access the raw methods on +} + +// Erc20WrapperCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc20WrapperCallerRaw struct { + Contract *Erc20WrapperCaller // Generic read-only contract binding to access the raw methods on +} + +// Erc20WrapperTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc20WrapperTransactorRaw struct { + Contract *Erc20WrapperTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc20Wrapper creates a new instance of Erc20Wrapper, bound to a specific deployed contract. +func NewErc20Wrapper(address common.Address, backend bind.ContractBackend) (*Erc20Wrapper, error) { + contract, err := bindErc20Wrapper(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc20Wrapper{Erc20WrapperCaller: Erc20WrapperCaller{contract: contract}, Erc20WrapperTransactor: Erc20WrapperTransactor{contract: contract}, Erc20WrapperFilterer: Erc20WrapperFilterer{contract: contract}}, nil +} + +// NewErc20WrapperCaller creates a new read-only instance of Erc20Wrapper, bound to a specific deployed contract. +func NewErc20WrapperCaller(address common.Address, caller bind.ContractCaller) (*Erc20WrapperCaller, error) { + contract, err := bindErc20Wrapper(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc20WrapperCaller{contract: contract}, nil +} + +// NewErc20WrapperTransactor creates a new write-only instance of Erc20Wrapper, bound to a specific deployed contract. +func NewErc20WrapperTransactor(address common.Address, transactor bind.ContractTransactor) (*Erc20WrapperTransactor, error) { + contract, err := bindErc20Wrapper(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc20WrapperTransactor{contract: contract}, nil +} + +// NewErc20WrapperFilterer creates a new log filterer instance of Erc20Wrapper, bound to a specific deployed contract. +func NewErc20WrapperFilterer(address common.Address, filterer bind.ContractFilterer) (*Erc20WrapperFilterer, error) { + contract, err := bindErc20Wrapper(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc20WrapperFilterer{contract: contract}, nil +} + +// bindErc20Wrapper binds a generic wrapper to an already deployed contract. +func bindErc20Wrapper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Erc20WrapperMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc20Wrapper *Erc20WrapperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Wrapper.Contract.Erc20WrapperCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc20Wrapper *Erc20WrapperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Erc20WrapperTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Wrapper *Erc20WrapperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Erc20WrapperTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Erc20Wrapper *Erc20WrapperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Wrapper.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Erc20Wrapper *Erc20WrapperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Wrapper *Erc20WrapperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.contract.Transact(opts, method, params...) +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_Erc20Wrapper *Erc20WrapperCaller) Factory(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Erc20Wrapper.contract.Call(opts, &out, "factory") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_Erc20Wrapper *Erc20WrapperSession) Factory() (common.Address, error) { + return _Erc20Wrapper.Contract.Factory(&_Erc20Wrapper.CallOpts) +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_Erc20Wrapper *Erc20WrapperCallerSession) Factory() (common.Address, error) { + return _Erc20Wrapper.Contract.Factory(&_Erc20Wrapper.CallOpts) +} + +// OriginTokens is a free data retrieval call binding the contract method 0xb5ad1fb6. +// +// Solidity: function originTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperCaller) OriginTokens(opts *bind.CallOpts, arg0 common.Address) (common.Address, error) { + var out []interface{} + err := _Erc20Wrapper.contract.Call(opts, &out, "originTokens", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// OriginTokens is a free data retrieval call binding the contract method 0xb5ad1fb6. +// +// Solidity: function originTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperSession) OriginTokens(arg0 common.Address) (common.Address, error) { + return _Erc20Wrapper.Contract.OriginTokens(&_Erc20Wrapper.CallOpts, arg0) +} + +// OriginTokens is a free data retrieval call binding the contract method 0xb5ad1fb6. +// +// Solidity: function originTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperCallerSession) OriginTokens(arg0 common.Address) (common.Address, error) { + return _Erc20Wrapper.Contract.OriginTokens(&_Erc20Wrapper.CallOpts, arg0) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20Wrapper *Erc20WrapperCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Erc20Wrapper.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20Wrapper *Erc20WrapperSession) Owner() (common.Address, error) { + return _Erc20Wrapper.Contract.Owner(&_Erc20Wrapper.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20Wrapper *Erc20WrapperCallerSession) Owner() (common.Address, error) { + return _Erc20Wrapper.Contract.Owner(&_Erc20Wrapper.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc20Wrapper *Erc20WrapperCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Erc20Wrapper.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc20Wrapper *Erc20WrapperSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Erc20Wrapper.Contract.SupportsInterface(&_Erc20Wrapper.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Erc20Wrapper *Erc20WrapperCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Erc20Wrapper.Contract.SupportsInterface(&_Erc20Wrapper.CallOpts, interfaceId) +} + +// WrappedTokens is a free data retrieval call binding the contract method 0xd5c6b504. +// +// Solidity: function wrappedTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperCaller) WrappedTokens(opts *bind.CallOpts, arg0 common.Address) (common.Address, error) { + var out []interface{} + err := _Erc20Wrapper.contract.Call(opts, &out, "wrappedTokens", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WrappedTokens is a free data retrieval call binding the contract method 0xd5c6b504. +// +// Solidity: function wrappedTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperSession) WrappedTokens(arg0 common.Address) (common.Address, error) { + return _Erc20Wrapper.Contract.WrappedTokens(&_Erc20Wrapper.CallOpts, arg0) +} + +// WrappedTokens is a free data retrieval call binding the contract method 0xd5c6b504. +// +// Solidity: function wrappedTokens(address ) view returns(address) +func (_Erc20Wrapper *Erc20WrapperCallerSession) WrappedTokens(arg0 common.Address) (common.Address, error) { + return _Erc20Wrapper.Contract.WrappedTokens(&_Erc20Wrapper.CallOpts, arg0) +} + +// CreateERC20 is a paid mutator transaction binding the contract method 0x06ef1a86. +// +// Solidity: function createERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Erc20Wrapper *Erc20WrapperTransactor) CreateERC20(opts *bind.TransactOpts, name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "createERC20", name, symbol, decimals) +} + +// CreateERC20 is a paid mutator transaction binding the contract method 0x06ef1a86. +// +// Solidity: function createERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Erc20Wrapper *Erc20WrapperSession) CreateERC20(name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.CreateERC20(&_Erc20Wrapper.TransactOpts, name, symbol, decimals) +} + +// CreateERC20 is a paid mutator transaction binding the contract method 0x06ef1a86. +// +// Solidity: function createERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Erc20Wrapper *Erc20WrapperTransactorSession) CreateERC20(name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.CreateERC20(&_Erc20Wrapper.TransactOpts, name, symbol, decimals) +} + +// IbcAck is a paid mutator transaction binding the contract method 0x0d4f1f9d. +// +// Solidity: function ibc_ack(uint64 callback_id, bool success) returns() +func (_Erc20Wrapper *Erc20WrapperTransactor) IbcAck(opts *bind.TransactOpts, callback_id uint64, success bool) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "ibc_ack", callback_id, success) +} + +// IbcAck is a paid mutator transaction binding the contract method 0x0d4f1f9d. +// +// Solidity: function ibc_ack(uint64 callback_id, bool success) returns() +func (_Erc20Wrapper *Erc20WrapperSession) IbcAck(callback_id uint64, success bool) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.IbcAck(&_Erc20Wrapper.TransactOpts, callback_id, success) +} + +// IbcAck is a paid mutator transaction binding the contract method 0x0d4f1f9d. +// +// Solidity: function ibc_ack(uint64 callback_id, bool success) returns() +func (_Erc20Wrapper *Erc20WrapperTransactorSession) IbcAck(callback_id uint64, success bool) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.IbcAck(&_Erc20Wrapper.TransactOpts, callback_id, success) +} + +// IbcTimeout is a paid mutator transaction binding the contract method 0x31a503f0. +// +// Solidity: function ibc_timeout(uint64 callback_id) returns() +func (_Erc20Wrapper *Erc20WrapperTransactor) IbcTimeout(opts *bind.TransactOpts, callback_id uint64) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "ibc_timeout", callback_id) +} + +// IbcTimeout is a paid mutator transaction binding the contract method 0x31a503f0. +// +// Solidity: function ibc_timeout(uint64 callback_id) returns() +func (_Erc20Wrapper *Erc20WrapperSession) IbcTimeout(callback_id uint64) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.IbcTimeout(&_Erc20Wrapper.TransactOpts, callback_id) +} + +// IbcTimeout is a paid mutator transaction binding the contract method 0x31a503f0. +// +// Solidity: function ibc_timeout(uint64 callback_id) returns() +func (_Erc20Wrapper *Erc20WrapperTransactorSession) IbcTimeout(callback_id uint64) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.IbcTimeout(&_Erc20Wrapper.TransactOpts, callback_id) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20Wrapper *Erc20WrapperTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20Wrapper *Erc20WrapperSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.TransferOwnership(&_Erc20Wrapper.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20Wrapper *Erc20WrapperTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.TransferOwnership(&_Erc20Wrapper.TransactOpts, newOwner) +} + +// Unwrap is a paid mutator transaction binding the contract method 0xfc078758. +// +// Solidity: function unwrap(string wrappedTokenDenom, address receiver, uint256 wrappedAmt) returns() +func (_Erc20Wrapper *Erc20WrapperTransactor) Unwrap(opts *bind.TransactOpts, wrappedTokenDenom string, receiver common.Address, wrappedAmt *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "unwrap", wrappedTokenDenom, receiver, wrappedAmt) +} + +// Unwrap is a paid mutator transaction binding the contract method 0xfc078758. +// +// Solidity: function unwrap(string wrappedTokenDenom, address receiver, uint256 wrappedAmt) returns() +func (_Erc20Wrapper *Erc20WrapperSession) Unwrap(wrappedTokenDenom string, receiver common.Address, wrappedAmt *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Unwrap(&_Erc20Wrapper.TransactOpts, wrappedTokenDenom, receiver, wrappedAmt) +} + +// Unwrap is a paid mutator transaction binding the contract method 0xfc078758. +// +// Solidity: function unwrap(string wrappedTokenDenom, address receiver, uint256 wrappedAmt) returns() +func (_Erc20Wrapper *Erc20WrapperTransactorSession) Unwrap(wrappedTokenDenom string, receiver common.Address, wrappedAmt *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Unwrap(&_Erc20Wrapper.TransactOpts, wrappedTokenDenom, receiver, wrappedAmt) +} + +// Wrap is a paid mutator transaction binding the contract method 0x9a111432. +// +// Solidity: function wrap(string channel, address token, string receiver, uint256 amount, uint256 timeout) returns() +func (_Erc20Wrapper *Erc20WrapperTransactor) Wrap(opts *bind.TransactOpts, channel string, token common.Address, receiver string, amount *big.Int, timeout *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.contract.Transact(opts, "wrap", channel, token, receiver, amount, timeout) +} + +// Wrap is a paid mutator transaction binding the contract method 0x9a111432. +// +// Solidity: function wrap(string channel, address token, string receiver, uint256 amount, uint256 timeout) returns() +func (_Erc20Wrapper *Erc20WrapperSession) Wrap(channel string, token common.Address, receiver string, amount *big.Int, timeout *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Wrap(&_Erc20Wrapper.TransactOpts, channel, token, receiver, amount, timeout) +} + +// Wrap is a paid mutator transaction binding the contract method 0x9a111432. +// +// Solidity: function wrap(string channel, address token, string receiver, uint256 amount, uint256 timeout) returns() +func (_Erc20Wrapper *Erc20WrapperTransactorSession) Wrap(channel string, token common.Address, receiver string, amount *big.Int, timeout *big.Int) (*types.Transaction, error) { + return _Erc20Wrapper.Contract.Wrap(&_Erc20Wrapper.TransactOpts, channel, token, receiver, amount, timeout) +} + +// Erc20WrapperERC20CreatedIterator is returned from FilterERC20Created and is used to iterate over the raw logs and unpacked data for ERC20Created events raised by the Erc20Wrapper contract. +type Erc20WrapperERC20CreatedIterator struct { + Event *Erc20WrapperERC20Created // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc20WrapperERC20CreatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc20WrapperERC20Created) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc20WrapperERC20Created) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc20WrapperERC20CreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20WrapperERC20CreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20WrapperERC20Created represents a ERC20Created event raised by the Erc20Wrapper contract. +type Erc20WrapperERC20Created struct { + Erc20 common.Address + Owner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterERC20Created is a free log retrieval operation binding the contract event 0x85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d1. +// +// Solidity: event ERC20Created(address indexed erc20, address indexed owner) +func (_Erc20Wrapper *Erc20WrapperFilterer) FilterERC20Created(opts *bind.FilterOpts, erc20 []common.Address, owner []common.Address) (*Erc20WrapperERC20CreatedIterator, error) { + + var erc20Rule []interface{} + for _, erc20Item := range erc20 { + erc20Rule = append(erc20Rule, erc20Item) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _Erc20Wrapper.contract.FilterLogs(opts, "ERC20Created", erc20Rule, ownerRule) + if err != nil { + return nil, err + } + return &Erc20WrapperERC20CreatedIterator{contract: _Erc20Wrapper.contract, event: "ERC20Created", logs: logs, sub: sub}, nil +} + +// WatchERC20Created is a free log subscription operation binding the contract event 0x85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d1. +// +// Solidity: event ERC20Created(address indexed erc20, address indexed owner) +func (_Erc20Wrapper *Erc20WrapperFilterer) WatchERC20Created(opts *bind.WatchOpts, sink chan<- *Erc20WrapperERC20Created, erc20 []common.Address, owner []common.Address) (event.Subscription, error) { + + var erc20Rule []interface{} + for _, erc20Item := range erc20 { + erc20Rule = append(erc20Rule, erc20Item) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _Erc20Wrapper.contract.WatchLogs(opts, "ERC20Created", erc20Rule, ownerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc20WrapperERC20Created) + if err := _Erc20Wrapper.contract.UnpackLog(event, "ERC20Created", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseERC20Created is a log parse operation binding the contract event 0x85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d1. +// +// Solidity: event ERC20Created(address indexed erc20, address indexed owner) +func (_Erc20Wrapper *Erc20WrapperFilterer) ParseERC20Created(log types.Log) (*Erc20WrapperERC20Created, error) { + event := new(Erc20WrapperERC20Created) + if err := _Erc20Wrapper.contract.UnpackLog(event, "ERC20Created", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc20WrapperOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Erc20Wrapper contract. +type Erc20WrapperOwnershipTransferredIterator struct { + Event *Erc20WrapperOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Erc20WrapperOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Erc20WrapperOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Erc20WrapperOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Erc20WrapperOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20WrapperOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20WrapperOwnershipTransferred represents a OwnershipTransferred event raised by the Erc20Wrapper contract. +type Erc20WrapperOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20Wrapper *Erc20WrapperFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*Erc20WrapperOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Erc20Wrapper.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Erc20WrapperOwnershipTransferredIterator{contract: _Erc20Wrapper.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20Wrapper *Erc20WrapperFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *Erc20WrapperOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Erc20Wrapper.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Erc20WrapperOwnershipTransferred) + if err := _Erc20Wrapper.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Erc20Wrapper *Erc20WrapperFilterer) ParseOwnershipTransferred(log types.Log) (*Erc20WrapperOwnershipTransferred, error) { + event := new(Erc20WrapperOwnershipTransferred) + if err := _Erc20Wrapper.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol b/x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol new file mode 100644 index 0000000..106a8ba --- /dev/null +++ b/x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../util/Strings.sol"; +import "../i_cosmos/ICosmos.sol"; +import "../erc20_factory/ERC20Factory.sol"; +import "../i_erc20/IERC20.sol"; +import "../ownable/Ownable.sol"; +import "../erc20_registry/ERC20Registry.sol"; +import "../erc20_acl/ERC20ACL.sol"; +import {ERC165, IERC165} from "../erc165/ERC165.sol"; + +contract ERC20Wrapper is + Ownable, + ERC20Registry, + ERC165, + ERC20ACL, + ERC20Factory +{ + struct IbcCallBack { + address sender; + string wrappedTokenDenom; + uint wrappedAmt; + } + + uint8 constant WRAPPED_DECIMAL = 6; + string constant NAME_PREFIX = "Wrapped"; + string constant SYMBOL_PREFIX = "W"; + uint64 callBackId = 0; + ERC20Factory public immutable factory; + mapping(address => address) public wrappedTokens; // origin -> wrapped + mapping(address => address) public originTokens; // wrapped -> origin + mapping(uint64 => IbcCallBack) private ibcCallBack; // id -> CallBackInfo + + constructor(address erc20Factory) { + factory = ERC20Factory(erc20Factory); + } + + /** + * @notice This function wraps the tokens and transfer the tokens by ibc transfer + * @dev A sender requires sender approve to this contract to transfer the tokens. + */ + function wrap( + string memory channel, + address token, + string memory receiver, + uint amount, + uint timeout + ) public { + _ensureWrappedTokenExists(token); + + // lock origin token + IERC20(token).transferFrom(msg.sender, address(this), amount); + uint wrappedAmt = _convertDecimal( + amount, + IERC20(token).decimals(), + WRAPPED_DECIMAL + ); + // mint wrapped token + ERC20(wrappedTokens[token]).mint(address(this), wrappedAmt); + + callBackId += 1; + + // store the callback data + ibcCallBack[callBackId] = IbcCallBack({ + sender: msg.sender, + wrappedTokenDenom: COSMOS_CONTRACT.to_denom(wrappedTokens[token]), + wrappedAmt: wrappedAmt + }); + + // do ibc transfer wrapped token + COSMOS_CONTRACT.execute_cosmos( + _ibc_transfer( + channel, + wrappedTokens[token], + wrappedAmt, + timeout, + receiver + ) + ); + } + + /** + * @notice This function is executed as an IBC hook to unwrap the wrapped tokens. + * @dev This function is used by a hook and requires sender approve to this contract to burn wrapped tokens. + */ + function unwrap( + string memory wrappedTokenDenom, + address receiver, + uint wrappedAmt + ) public { + address wrappedToken = COSMOS_CONTRACT.to_erc20(wrappedTokenDenom); + require( + originTokens[wrappedToken] != address(0), + "origin token doesn't exist" + ); + + // burn wrapped token + ERC20(wrappedToken).burnFrom(msg.sender, wrappedAmt); + + // unlock origin token and transfer to receiver + uint amount = _convertDecimal( + wrappedAmt, + WRAPPED_DECIMAL, + IERC20(originTokens[wrappedToken]).decimals() + ); + + ERC20(originTokens[wrappedToken]).transfer(receiver, amount); + } + + function ibc_ack(uint64 callback_id, bool success) external { + if (success) { + return; + } + _handleFailedIbcTransfer(callback_id); + } + + function ibc_timeout(uint64 callback_id) external { + _handleFailedIbcTransfer(callback_id); + } + + // internal functions // + + function _handleFailedIbcTransfer(uint64 callback_id) internal { + IbcCallBack memory callback = ibcCallBack[callback_id]; + unwrap( + callback.wrappedTokenDenom, + callback.sender, + callback.wrappedAmt + ); + } + + function _ensureWrappedTokenExists(address token) internal { + if (wrappedTokens[token] == address(0)) { + address wrappedToken = factory.createERC20( + string.concat(NAME_PREFIX, IERC20(token).name()), + string.concat(SYMBOL_PREFIX, IERC20(token).symbol()), + WRAPPED_DECIMAL + ); + wrappedTokens[token] = wrappedToken; + originTokens[wrappedToken] = token; + } + } + + function _convertDecimal( + uint amount, + uint8 decimal, + uint8 newDecimal + ) internal pure returns (uint convertedAmount) { + if (decimal > newDecimal) { + uint factor = 10 ** uint(decimal - newDecimal); + convertedAmount = amount / factor; + } else if (decimal < newDecimal) { + uint factor = 10 ** uint(newDecimal - decimal); + convertedAmount = amount * factor; + } else { + convertedAmount = amount; + } + require(convertedAmount != 0, "converted amount is zero"); + } + + function _ibc_transfer( + string memory channel, + address token, + uint amount, + uint timeout, + string memory receiver + ) internal returns (string memory message) { + // Construct the IBC transfer message + message = string( + abi.encodePacked( + '{"@type": "/ibc.applications.transfer.v1.MsgTransfer",', + '"source_port": "transfer",', + '"source_channel": "', + channel, + '",', + '"token": { "denom": "', + COSMOS_CONTRACT.to_denom(token), + '",', + '"amount": "', + Strings.toString(amount), + '"},', + '"sender": "', + COSMOS_CONTRACT.to_cosmos_address(address(this)), + '",', + '"receiver": "', + receiver, + '",', + '"timeout_height": {"revision_number": "0","revision_height": "0"},', + '"timeout_timestamp": "', + Strings.toString(timeout), + '",', + '"memo": "",', + '"async_callback": {"id": "', + Strings.toString(callBackId), + '",', + '"contract_address": "', + Strings.toHexString(address(this)), + '"}}' + ) + ); + } +} diff --git a/x/evm/contracts/util/Strings.go b/x/evm/contracts/util/Strings.go new file mode 100644 index 0000000..4424517 --- /dev/null +++ b/x/evm/contracts/util/Strings.go @@ -0,0 +1,203 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package util + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// UtilMetaData contains all meta data concerning the Util contract. +var UtilMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"StringsInsufficientHexLength\",\"type\":\"error\"}]", + Bin: "0x6055604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f80fdfea2646970667358221220c8a20e32684b8eb475517477c61e8fbe77e3c5335efa1a66ec78960a607261e064736f6c63430008190033", +} + +// UtilABI is the input ABI used to generate the binding from. +// Deprecated: Use UtilMetaData.ABI instead. +var UtilABI = UtilMetaData.ABI + +// UtilBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use UtilMetaData.Bin instead. +var UtilBin = UtilMetaData.Bin + +// DeployUtil deploys a new Ethereum contract, binding an instance of Util to it. +func DeployUtil(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Util, error) { + parsed, err := UtilMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(UtilBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Util{UtilCaller: UtilCaller{contract: contract}, UtilTransactor: UtilTransactor{contract: contract}, UtilFilterer: UtilFilterer{contract: contract}}, nil +} + +// Util is an auto generated Go binding around an Ethereum contract. +type Util struct { + UtilCaller // Read-only binding to the contract + UtilTransactor // Write-only binding to the contract + UtilFilterer // Log filterer for contract events +} + +// UtilCaller is an auto generated read-only Go binding around an Ethereum contract. +type UtilCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// UtilTransactor is an auto generated write-only Go binding around an Ethereum contract. +type UtilTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// UtilFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type UtilFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// UtilSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type UtilSession struct { + Contract *Util // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// UtilCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type UtilCallerSession struct { + Contract *UtilCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// UtilTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type UtilTransactorSession struct { + Contract *UtilTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// UtilRaw is an auto generated low-level Go binding around an Ethereum contract. +type UtilRaw struct { + Contract *Util // Generic contract binding to access the raw methods on +} + +// UtilCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type UtilCallerRaw struct { + Contract *UtilCaller // Generic read-only contract binding to access the raw methods on +} + +// UtilTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type UtilTransactorRaw struct { + Contract *UtilTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewUtil creates a new instance of Util, bound to a specific deployed contract. +func NewUtil(address common.Address, backend bind.ContractBackend) (*Util, error) { + contract, err := bindUtil(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Util{UtilCaller: UtilCaller{contract: contract}, UtilTransactor: UtilTransactor{contract: contract}, UtilFilterer: UtilFilterer{contract: contract}}, nil +} + +// NewUtilCaller creates a new read-only instance of Util, bound to a specific deployed contract. +func NewUtilCaller(address common.Address, caller bind.ContractCaller) (*UtilCaller, error) { + contract, err := bindUtil(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &UtilCaller{contract: contract}, nil +} + +// NewUtilTransactor creates a new write-only instance of Util, bound to a specific deployed contract. +func NewUtilTransactor(address common.Address, transactor bind.ContractTransactor) (*UtilTransactor, error) { + contract, err := bindUtil(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &UtilTransactor{contract: contract}, nil +} + +// NewUtilFilterer creates a new log filterer instance of Util, bound to a specific deployed contract. +func NewUtilFilterer(address common.Address, filterer bind.ContractFilterer) (*UtilFilterer, error) { + contract, err := bindUtil(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &UtilFilterer{contract: contract}, nil +} + +// bindUtil binds a generic wrapper to an already deployed contract. +func bindUtil(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := UtilMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Util *UtilRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Util.Contract.UtilCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Util *UtilRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Util.Contract.UtilTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Util *UtilRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Util.Contract.UtilTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Util *UtilCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Util.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Util *UtilTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Util.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Util *UtilTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Util.Contract.contract.Transact(opts, method, params...) +} diff --git a/x/evm/contracts/util/Strings.sol b/x/evm/contracts/util/Strings.sol new file mode 100644 index 0000000..415c5a2 --- /dev/null +++ b/x/evm/contracts/util/Strings.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +//ref. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol +library Strings { + bytes16 private constant HEX_DIGITS = "0123456789abcdef"; + uint8 private constant ADDRESS_LENGTH = 20; + /** + * @dev The `value` string doesn't fit in the specified `length`. + */ + error StringsInsufficientHexLength(uint256 value, uint256 length); + + function toHexString( + uint256 value, + uint256 length + ) internal pure returns (string memory) { + uint256 localValue = value; + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = HEX_DIGITS[localValue & 0xf]; + localValue >>= 4; + } + if (localValue != 0) { + revert StringsInsufficientHexLength(value, length); + } + return string(buffer); + } + + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); + } + + function toString(uint256 value) internal pure returns (string memory) { + unchecked { + uint256 length = log10(value) + 1; + string memory buffer = new string(length); + uint256 ptr; + assembly ("memory-safe") { + ptr := add(buffer, add(32, length)) + } + while (true) { + ptr--; + assembly ("memory-safe") { + mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) + } + value /= 10; + if (value == 0) break; + } + return buffer; + } + } + + function log10(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >= 10 ** 64) { + value /= 10 ** 64; + result += 64; + } + if (value >= 10 ** 32) { + value /= 10 ** 32; + result += 32; + } + if (value >= 10 ** 16) { + value /= 10 ** 16; + result += 16; + } + if (value >= 10 ** 8) { + value /= 10 ** 8; + result += 8; + } + if (value >= 10 ** 4) { + value /= 10 ** 4; + result += 4; + } + if (value >= 10 ** 2) { + value /= 10 ** 2; + result += 2; + } + if (value >= 10 ** 1) { + result += 1; + } + } + return result; + } +} diff --git a/x/evm/keeper/erc721_test.go b/x/evm/keeper/erc721_test.go index b99e219..362c8f6 100644 --- a/x/evm/keeper/erc721_test.go +++ b/x/evm/keeper/erc721_test.go @@ -20,7 +20,7 @@ func Test_CreateCollection(t *testing.T) { classId := "test-class-id" classUri := "test-class-uri" - contractAddr := crypto.CreateAddress(types.StdAddress, 1) + contractAddr := crypto.CreateAddress(types.StdAddress, 2) err = erc721Keeper.CreateOrUpdateClass(ctx, classId, classUri, "") require.NoError(t, err) diff --git a/x/evm/keeper/genesis.go b/x/evm/keeper/genesis.go index b06e424..bfc7ac0 100644 --- a/x/evm/keeper/genesis.go +++ b/x/evm/keeper/genesis.go @@ -9,25 +9,27 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/initia-labs/minievm/x/evm/contracts/erc20_factory" + "github.com/initia-labs/minievm/x/evm/contracts/erc20_wrapper" "github.com/initia-labs/minievm/x/evm/types" ) -// Initialize initializes the EVM state at genesis -// 1. deploy and store erc20 factory contract -// 2. deploy fee denom erc20 coins at genesis bootstrapping with 18 decimals +// Initialize initializes the EVM state at genesis by performing the following steps: +// 1. Deploy and store the ERC20 factory contract. +// 2. Deploy fee denom ERC20 coins at genesis bootstrapping with 18 decimals. +// 3. Deploy and store the wrapper ERC20 factory contract for IBC transfers to the destination chain (not compatible due to 18 decimals). func (k Keeper) Initialize(ctx context.Context) error { return k.InitializeWithDecimals(ctx, types.EtherDecimals) } // InitializeWithDecimals initializes the EVM state at genesis with the given decimals func (k Keeper) InitializeWithDecimals(ctx context.Context, decimals uint8) error { - // 1. deploy and store erc20 factory contract - code, err := hexutil.Decode(erc20_factory.Erc20FactoryBin) + // 1. Deploy and store the ERC20 factory contract. + factoryCode, err := hexutil.Decode(erc20_factory.Erc20FactoryBin) if err != nil { return err } - _, factoryAddr, _, err := k.EVMCreate2(ctx, types.StdAddress, code, nil, types.ERC20FactorySalt, nil) + _, factoryAddr, _, err := k.EVMCreate2(ctx, types.StdAddress, factoryCode, nil, types.ERC20FactorySalt, nil) if err != nil { return err } @@ -42,12 +44,33 @@ func (k Keeper) InitializeWithDecimals(ctx context.Context, decimals uint8) erro return err } - // 2. deploy fee denom erc20 coins at genesis bootstrapping + // 2. Deploy fee denom ERC20 coins at genesis bootstrapping with decimals. err = k.erc20Keeper.CreateERC20(ctx, params.FeeDenom, decimals) if err != nil { return err } + // 3. Deploy and store the wrapper ERC20 factory contract for IBC transfers to the destination chain (not compatible due to 18 decimals). + wrapperCode, err := hexutil.Decode(erc20_wrapper.Erc20WrapperBin) + if err != nil { + return err + } + abi, _ := erc20_wrapper.Erc20WrapperMetaData.GetAbi() + wrapperConstructorArg, err := abi.Constructor.Inputs.Pack(factoryAddr) + if err != nil { + return err + } + + _, wrapperAddr, _, err := k.EVMCreate2(ctx, types.StdAddress, append(wrapperCode, wrapperConstructorArg...), nil, types.ERC20WrapperSalt, nil) + if err != nil { + return err + } + + err = k.ERC20WrapperAddr.Set(ctx, wrapperAddr.Bytes()) + if err != nil { + return err + } + return nil } @@ -65,6 +88,9 @@ func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) er if err := k.ERC20FactoryAddr.Set(ctx, genState.Erc20Factory); err != nil { return err } + if err := k.ERC20WrapperAddr.Set(ctx, genState.Erc20Wrapper); err != nil { + return err + } } for _, kv := range genState.KeyValues { @@ -214,6 +240,11 @@ func (k Keeper) ExportGenesis(ctx context.Context) *types.GenesisState { panic(err) } + wrapperAddr, err := k.ERC20WrapperAddr.Get(ctx) + if err != nil { + panic(err) + } + return &types.GenesisState{ Params: params, KeyValues: kvs, @@ -222,6 +253,7 @@ func (k Keeper) ExportGenesis(ctx context.Context) *types.GenesisState { DenomTraces: denomTraces, ClassTraces: classTraces, Erc20Factory: factoryAddr, + Erc20Wrapper: wrapperAddr, EVMBlockHashes: evmBlockHashes, } } diff --git a/x/evm/keeper/genesis_test.go b/x/evm/keeper/genesis_test.go index 7008cde..54f4c2b 100644 --- a/x/evm/keeper/genesis_test.go +++ b/x/evm/keeper/genesis_test.go @@ -3,6 +3,8 @@ package keeper_test import ( "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/initia-labs/minievm/x/evm/contracts/erc20_wrapper" "github.com/initia-labs/minievm/x/evm/types" "github.com/stretchr/testify/require" ) @@ -16,6 +18,7 @@ func Test_Genesis(t *testing.T) { {1, 2, 3}, {4, 5, 6}, } + genState.Erc20Wrapper = []byte{5, 6, 7, 8} genState.Erc20Stores = []types.GenesisERC20Stores{ { Address: []byte{1, 2, 3}, @@ -78,3 +81,25 @@ func Test_Genesis(t *testing.T) { _genState := input.EVMKeeper.ExportGenesis(ctx) require.Equal(t, genState, _genState) } + +func Test_Initialize(t *testing.T) { + ctx, input := createTestInput(t, false, true) + wrapperAddr, err := input.EVMKeeper.GetERC20WrapperAddr(ctx) + require.NoError(t, err) + + caller := common.HexToAddress("0x0") + abi, err := erc20_wrapper.Erc20WrapperMetaData.GetAbi() + require.NoError(t, err) + + viewArg, err := abi.Pack("factory") + require.NoError(t, err) + + factoryAddrBytes, err := input.EVMKeeper.EVMStaticCall(ctx, caller, wrapperAddr, viewArg, nil) + require.NoError(t, err) + + factoryAddr := common.BytesToAddress(factoryAddrBytes) + expectedFactoryAddr, err := input.EVMKeeper.GetERC20FactoryAddr(ctx) + require.NoError(t, err) + + require.Equal(t, expectedFactoryAddr, factoryAddr) +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 3b355e5..9842ad1 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -60,6 +60,7 @@ type Keeper struct { // erc20 stores of users ERC20FactoryAddr collections.Item[[]byte] + ERC20WrapperAddr collections.Item[[]byte] ERC20s collections.KeySet[[]byte] ERC20Stores collections.KeySet[collections.Pair[[]byte, []byte]] ERC20DenomsByContractAddr collections.Map[[]byte, string] @@ -129,6 +130,7 @@ func NewKeeper( TransientAccessList: collections.NewKeySet(tsb, types.TransientAccessListPrefix, "transient_access_list", collections.PairKeyCodec(collections.Uint64Key, collections.BytesKey)), TransientRefund: collections.NewMap(tsb, types.TransientRefundPrefix, "transient_refund", collections.Uint64Key, collections.Uint64Value), + ERC20WrapperAddr: collections.NewItem(sb, types.ERC20WrapperAddrKey, "erc20_wrapper_addr", collections.BytesValue), ERC20FactoryAddr: collections.NewItem(sb, types.ERC20FactoryAddrKey, "erc20_factory_addr", collections.BytesValue), ERC20s: collections.NewKeySet(sb, types.ERC20sPrefix, "erc20s", collections.BytesKey), ERC20Stores: collections.NewKeySet(sb, types.ERC20StoresPrefix, "erc20_stores", collections.PairKeyCodec(collections.BytesKey, collections.BytesKey)), @@ -253,6 +255,15 @@ func (k Keeper) GetERC20FactoryAddr(ctx context.Context) (common.Address, error) return common.BytesToAddress(factoryAddr), nil } +func (k Keeper) GetERC20WrapperAddr(ctx context.Context) (common.Address, error) { + wrapperAddr, err := k.ERC20WrapperAddr.Get(ctx) + if err != nil { + return common.Address{}, types.ErrFailedToGetERC20WrapperAddr.Wrap(err.Error()) + } + + return common.BytesToAddress(wrapperAddr), nil +} + // keep track recent 256 block hashes // - https://www.ethervm.io/#40 func (k Keeper) TrackBlockHash(ctx context.Context, blockHeight uint64, hash common.Hash) error { diff --git a/x/evm/keeper/query_server.go b/x/evm/keeper/query_server.go index ea9e2a5..165b268 100644 --- a/x/evm/keeper/query_server.go +++ b/x/evm/keeper/query_server.go @@ -156,6 +156,18 @@ func (qs *queryServerImpl) ERC20Factory(ctx context.Context, req *types.QueryERC }, nil } +// ERC20Wrapper implements types.QueryServer. +func (qs *queryServerImpl) ERC20Wrapper(ctx context.Context, req *types.QueryERC20WrapperRequest) (*types.QueryERC20WrapperResponse, error) { + wrapper, err := qs.Keeper.GetERC20WrapperAddr(ctx) + if err != nil { + return nil, err + } + + return &types.QueryERC20WrapperResponse{ + Address: wrapper.Hex(), + }, nil +} + // ContractAddrByDenom implements types.QueryServer. func (qs *queryServerImpl) ContractAddrByDenom(ctx context.Context, req *types.QueryContractAddrByDenomRequest) (*types.QueryContractAddrByDenomResponse, error) { contractAddr, err := types.DenomToContractAddr(ctx, qs, req.Denom) diff --git a/x/evm/keeper/query_server_test.go b/x/evm/keeper/query_server_test.go index 0a8e684..3726f45 100644 --- a/x/evm/keeper/query_server_test.go +++ b/x/evm/keeper/query_server_test.go @@ -64,3 +64,17 @@ func Test_Query_ERC20Factory(t *testing.T) { require.Equal(t, factoryAddr.Hex(), res.Address) } + +func Test_Query_ERC20Wrapper(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + wrapperAddr, err := input.EVMKeeper.GetERC20WrapperAddr(ctx) + require.NoError(t, err) + + qs := keeper.NewQueryServer(&input.EVMKeeper) + res, err := qs.ERC20Wrapper(ctx, &types.QueryERC20WrapperRequest{}) + require.NoError(t, err) + + require.Equal(t, wrapperAddr.Hex(), res.Address) +} + diff --git a/x/evm/types/address.go b/x/evm/types/address.go index 1734bd5..30b6e69 100644 --- a/x/evm/types/address.go +++ b/x/evm/types/address.go @@ -14,6 +14,7 @@ var StdAddress common.Address = common.HexToAddress("0x1") // ERC20FactorySalt is the salt used to create the ERC20 factory address var ERC20FactorySalt = uint64(1) +var ERC20WrapperSalt = uint64(2) // 0xf1 Cosmos precompile address var CosmosPrecompileAddress common.Address = common.HexToAddress("0xf1") diff --git a/x/evm/types/errors.go b/x/evm/types/errors.go index d619daa..e4e631e 100644 --- a/x/evm/types/errors.go +++ b/x/evm/types/errors.go @@ -34,6 +34,7 @@ var ( ErrFailedToGetERC20FactoryAddr = errorsmod.Register(ModuleName, 25, "Failed to get ERC20 factory address") ErrInvalidFeeDenom = errorsmod.Register(ModuleName, 26, "Invalid fee denom") ErrInvalidGasRefundRatio = errorsmod.Register(ModuleName, 27, "Invalid gas refund ratio") + ErrFailedToGetERC20WrapperAddr = errorsmod.Register(ModuleName, 28, "Failed to get ERC20 wrapper address") ) func NewRevertError(revert []byte) error { diff --git a/x/evm/types/genesis.pb.go b/x/evm/types/genesis.pb.go index 65bc6fb..7102999 100644 --- a/x/evm/types/genesis.pb.go +++ b/x/evm/types/genesis.pb.go @@ -38,6 +38,8 @@ type GenesisState struct { EVMBlockHashes []GenesisEVMBlockHash `protobuf:"bytes,7,rep,name=evm_block_hashes,json=evmBlockHashes,proto3" json:"evm_block_hashes" yaml:"evm_block_hashes"` // erc20 factory contract address Erc20Factory []byte `protobuf:"bytes,8,opt,name=erc20_factory,json=erc20Factory,proto3" json:"erc20_factory,omitempty"` + // erc20 wrapper contract address + Erc20Wrapper []byte `protobuf:"bytes,9,opt,name=erc20_wrapper,json=erc20Wrapper,proto3" json:"erc20_wrapper,omitempty"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -129,6 +131,13 @@ func (m *GenesisState) GetErc20Factory() []byte { return nil } +func (m *GenesisState) GetErc20Wrapper() []byte { + if m != nil { + return m.Erc20Wrapper + } + return nil +} + // GenesisKeyValue defines store KV values. type GenesisKeyValue struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` @@ -412,47 +421,47 @@ func init() { func init() { proto.RegisterFile("minievm/evm/v1/genesis.proto", fileDescriptor_2f1b77281e8b59af) } var fileDescriptor_2f1b77281e8b59af = []byte{ - // 626 bytes of a gzipped FileDescriptorProto + // 639 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xcd, 0x4e, 0xdb, 0x4c, 0x14, 0x86, 0x63, 0x12, 0x0c, 0x4c, 0xcc, 0xdf, 0x80, 0xf8, 0x0c, 0x7c, 0xb2, 0xd3, 0x61, 0x93, - 0x56, 0x6a, 0x42, 0x42, 0x37, 0xed, 0x0e, 0x43, 0x69, 0xab, 0xaa, 0x52, 0x35, 0x20, 0xa4, 0x76, - 0x63, 0x4d, 0xec, 0x69, 0x6c, 0x25, 0x8e, 0x23, 0x8f, 0x63, 0xd5, 0xbb, 0x5e, 0x42, 0xaf, 0xa2, - 0xd7, 0xc2, 0x92, 0x65, 0x57, 0x51, 0x95, 0xdc, 0x01, 0x57, 0x50, 0xcd, 0x4f, 0x42, 0x1a, 0x48, - 0xa5, 0x2e, 0x2c, 0x9d, 0x73, 0xe6, 0xf5, 0xf3, 0x8e, 0xce, 0x39, 0x1a, 0xf0, 0x7f, 0x14, 0xf6, - 0x42, 0x9a, 0x45, 0x75, 0xfe, 0x65, 0x8d, 0x7a, 0x9b, 0xf6, 0x28, 0x0b, 0x59, 0xad, 0x9f, 0xc4, - 0x69, 0x0c, 0x37, 0xd4, 0x69, 0x8d, 0x7f, 0x59, 0xe3, 0x60, 0xb7, 0x1d, 0xb7, 0x63, 0x71, 0x54, - 0xe7, 0x91, 0x54, 0x1d, 0x1c, 0xcc, 0x31, 0xd2, 0xbc, 0x4f, 0x15, 0x01, 0xfd, 0x58, 0x06, 0xc6, - 0x1b, 0xc9, 0xbc, 0x4c, 0x49, 0x4a, 0xe1, 0x0b, 0xa0, 0xf7, 0x49, 0x42, 0x22, 0x66, 0x6a, 0x15, - 0xad, 0x5a, 0x6e, 0xee, 0xd5, 0xfe, 0xf4, 0xa8, 0x7d, 0x14, 0xa7, 0x4e, 0xe9, 0x66, 0x68, 0x17, - 0xb0, 0xd2, 0xc2, 0x4f, 0x00, 0x74, 0x68, 0xee, 0x66, 0xa4, 0x3b, 0xa0, 0xcc, 0x5c, 0xaa, 0x14, - 0xab, 0xe5, 0xa6, 0x3d, 0xff, 0xa7, 0xf2, 0x79, 0x4f, 0xf3, 0x6b, 0xae, 0x73, 0xf6, 0x39, 0xe2, - 0x6e, 0x68, 0x6f, 0xe7, 0x24, 0xea, 0xbe, 0x42, 0xf7, 0x00, 0x84, 0xd7, 0x3a, 0x4a, 0xc4, 0xe0, - 0x09, 0xd0, 0x69, 0xe2, 0x35, 0x8f, 0x99, 0x59, 0xac, 0x14, 0xab, 0x86, 0x73, 0x38, 0x1a, 0xda, - 0xfa, 0x6b, 0x7c, 0xd6, 0x3c, 0x66, 0x77, 0x43, 0x7b, 0x5d, 0xfe, 0x2b, 0x15, 0x08, 0x2b, 0x29, - 0x6c, 0x01, 0x43, 0x44, 0x2e, 0x4b, 0xe3, 0x84, 0x32, 0xb3, 0x24, 0x6e, 0x84, 0x16, 0xdc, 0x48, - 0xd0, 0x2e, 0x85, 0xd2, 0x39, 0x54, 0x97, 0xda, 0x99, 0x01, 0x2b, 0x0a, 0xc2, 0x65, 0x91, 0x4a, - 0x25, 0x24, 0xc0, 0xf0, 0x69, 0x2f, 0x8e, 0xdc, 0x34, 0x21, 0x1e, 0x65, 0xe6, 0xb2, 0xf0, 0x78, - 0xb2, 0xc0, 0xe3, 0x9c, 0x4b, 0xaf, 0xb8, 0x72, 0xde, 0x62, 0x16, 0x82, 0x70, 0xd9, 0x9f, 0x0a, - 0x85, 0x85, 0xd7, 0x25, 0x8c, 0x4d, 0x2c, 0xf4, 0xbf, 0x5a, 0x9c, 0x71, 0xe9, 0xa3, 0x16, 0xb3, - 0x10, 0x84, 0xcb, 0xde, 0x54, 0xc8, 0xe0, 0x37, 0x0d, 0x6c, 0xd1, 0x2c, 0x72, 0x5b, 0xdd, 0xd8, - 0xeb, 0xb8, 0x01, 0x61, 0x01, 0x65, 0xe6, 0x8a, 0xf0, 0x39, 0x5a, 0xd4, 0xae, 0xeb, 0x0f, 0x0e, - 0x57, 0xbf, 0x25, 0x2c, 0x70, 0x1a, 0xdc, 0x69, 0x34, 0xb4, 0x37, 0x66, 0xab, 0x94, 0x8f, 0xe6, - 0x3f, 0xd5, 0xc1, 0x39, 0x38, 0xc2, 0x1b, 0x34, 0x8b, 0x66, 0xa4, 0xf0, 0x08, 0xac, 0xcb, 0x36, - 0x7f, 0x21, 0x5e, 0x1a, 0x27, 0xb9, 0xb9, 0x5a, 0xd1, 0xaa, 0x06, 0x96, 0x13, 0xbc, 0x90, 0x35, - 0xf4, 0x12, 0x6c, 0xce, 0xed, 0x0f, 0xdc, 0x02, 0xc5, 0x0e, 0xcd, 0xc5, 0x9e, 0x1a, 0x98, 0x87, - 0x70, 0x17, 0x2c, 0x8b, 0x0d, 0x32, 0x97, 0x44, 0x4d, 0x26, 0xe8, 0x02, 0xc0, 0x87, 0x83, 0x86, - 0x26, 0x58, 0x21, 0xbe, 0x9f, 0x50, 0xc6, 0x14, 0x61, 0x92, 0xc2, 0x3d, 0xa0, 0xab, 0xb5, 0xe1, - 0x8b, 0x6c, 0x60, 0x95, 0xa1, 0x2b, 0xb0, 0xfd, 0x60, 0x98, 0xdc, 0x52, 0x4c, 0x4c, 0x40, 0xd6, - 0xb0, 0x4c, 0xe0, 0x53, 0xb0, 0xe5, 0xc5, 0x3d, 0xde, 0xf0, 0xd4, 0x9d, 0xb8, 0xc8, 0x3b, 0x6d, - 0x4e, 0xea, 0xa7, 0xb2, 0x8c, 0x3a, 0x53, 0xea, 0xfd, 0xfc, 0xe0, 0x3e, 0x58, 0x95, 0x33, 0x0b, - 0x7d, 0x05, 0x5e, 0x11, 0xf9, 0x3b, 0xff, 0x1f, 0xd0, 0xbc, 0x41, 0x83, 0x24, 0x34, 0x8b, 0x02, - 0xc0, 0x43, 0x74, 0x0a, 0x76, 0x1e, 0x19, 0x22, 0x84, 0xa0, 0xc4, 0x87, 0xa3, 0x1a, 0x21, 0x62, - 0xde, 0x85, 0x80, 0x86, 0xed, 0x20, 0x15, 0xf4, 0x12, 0x56, 0x99, 0x73, 0x7e, 0x33, 0xb2, 0xb4, - 0xdb, 0x91, 0xa5, 0xfd, 0x1a, 0x59, 0xda, 0xf7, 0xb1, 0x55, 0xb8, 0x1d, 0x5b, 0x85, 0x9f, 0x63, - 0xab, 0xf0, 0xf9, 0x59, 0x3b, 0x4c, 0x83, 0x41, 0xab, 0xe6, 0xc5, 0x51, 0x3d, 0xec, 0x85, 0x69, - 0x48, 0x9e, 0x77, 0x49, 0x8b, 0xd5, 0x27, 0xcf, 0xcf, 0x57, 0xf1, 0x00, 0x89, 0xd7, 0xa7, 0xa5, - 0x8b, 0xe7, 0xe7, 0xe4, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x41, 0xe3, 0x75, 0x71, 0xe0, 0x04, - 0x00, 0x00, + 0x56, 0x6a, 0x02, 0xa1, 0x9b, 0x76, 0x87, 0xa1, 0xb4, 0x55, 0x55, 0xa9, 0x1a, 0x10, 0x55, 0xbb, + 0xb1, 0x26, 0xf6, 0x34, 0xb6, 0x12, 0xc7, 0x91, 0xc7, 0xb8, 0xf5, 0xae, 0x97, 0xd0, 0xcb, 0x42, + 0xea, 0x86, 0x65, 0x57, 0x51, 0x15, 0xee, 0x80, 0x2b, 0xa8, 0xe6, 0x27, 0xc4, 0x0d, 0xa4, 0x52, + 0x17, 0x96, 0xce, 0x39, 0xf3, 0xfa, 0x79, 0x47, 0xe7, 0x1c, 0x0d, 0xf8, 0x3f, 0x0a, 0xfb, 0x21, + 0xcd, 0xa2, 0x26, 0xff, 0xb2, 0x83, 0x66, 0x87, 0xf6, 0x29, 0x0b, 0x59, 0x63, 0x90, 0xc4, 0x69, + 0x0c, 0x57, 0xd4, 0x69, 0x83, 0x7f, 0xd9, 0xc1, 0xce, 0x66, 0x27, 0xee, 0xc4, 0xe2, 0xa8, 0xc9, + 0x23, 0xa9, 0xda, 0xd9, 0x99, 0x62, 0xa4, 0xf9, 0x80, 0x2a, 0x02, 0xfa, 0x31, 0x0f, 0x8c, 0x57, + 0x92, 0x79, 0x96, 0x92, 0x94, 0xc2, 0x67, 0x40, 0x1f, 0x90, 0x84, 0x44, 0xcc, 0xd4, 0x6a, 0x5a, + 0xbd, 0xda, 0xda, 0x6a, 0xfc, 0xe9, 0xd1, 0x78, 0x2f, 0x4e, 0x9d, 0xca, 0xd5, 0xd0, 0x2e, 0x61, + 0xa5, 0x85, 0x1f, 0x01, 0xe8, 0xd2, 0xdc, 0xcd, 0x48, 0xef, 0x92, 0x32, 0x73, 0xae, 0x56, 0xae, + 0x57, 0x5b, 0xf6, 0xf4, 0x9f, 0xca, 0xe7, 0x2d, 0xcd, 0x2f, 0xb8, 0xce, 0xd9, 0xe6, 0x88, 0xdb, + 0xa1, 0xbd, 0x9e, 0x93, 0xa8, 0xf7, 0x02, 0x4d, 0x00, 0x08, 0x2f, 0x75, 0x95, 0x88, 0xc1, 0x43, + 0xa0, 0xd3, 0xc4, 0x6b, 0xed, 0x33, 0xb3, 0x5c, 0x2b, 0xd7, 0x0d, 0x67, 0x77, 0x34, 0xb4, 0xf5, + 0x97, 0xf8, 0xb8, 0xb5, 0xcf, 0x6e, 0x87, 0xf6, 0xb2, 0xfc, 0x57, 0x2a, 0x10, 0x56, 0x52, 0xd8, + 0x06, 0x86, 0x88, 0x5c, 0x96, 0xc6, 0x09, 0x65, 0x66, 0x45, 0xdc, 0x08, 0xcd, 0xb8, 0x91, 0xa0, + 0x9d, 0x09, 0xa5, 0xb3, 0xab, 0x2e, 0xb5, 0x51, 0x00, 0x2b, 0x0a, 0xc2, 0x55, 0x91, 0x4a, 0x25, + 0x24, 0xc0, 0xf0, 0x69, 0x3f, 0x8e, 0xdc, 0x34, 0x21, 0x1e, 0x65, 0xe6, 0xbc, 0xf0, 0x78, 0x34, + 0xc3, 0xe3, 0x84, 0x4b, 0xcf, 0xb9, 0x72, 0xda, 0xa2, 0x08, 0x41, 0xb8, 0xea, 0xdf, 0x09, 0x85, + 0x85, 0xd7, 0x23, 0x8c, 0x8d, 0x2d, 0xf4, 0xbf, 0x5a, 0x1c, 0x73, 0xe9, 0x83, 0x16, 0x45, 0x08, + 0xc2, 0x55, 0xef, 0x4e, 0xc8, 0xe0, 0x37, 0x0d, 0xac, 0xd1, 0x2c, 0x72, 0xdb, 0xbd, 0xd8, 0xeb, + 0xba, 0x01, 0x61, 0x01, 0x65, 0xe6, 0x82, 0xf0, 0xd9, 0x9b, 0xd5, 0xae, 0x8b, 0x77, 0x0e, 0x57, + 0xbf, 0x26, 0x2c, 0x70, 0x0e, 0xb8, 0xd3, 0x68, 0x68, 0xaf, 0x14, 0xab, 0x94, 0x8f, 0xe6, 0x3f, + 0xd5, 0xc1, 0x29, 0x38, 0xc2, 0x2b, 0x34, 0x8b, 0x0a, 0x52, 0xb8, 0x07, 0x96, 0x65, 0x9b, 0x3f, + 0x13, 0x2f, 0x8d, 0x93, 0xdc, 0x5c, 0xac, 0x69, 0x75, 0x03, 0xcb, 0x09, 0x9e, 0xca, 0xda, 0x44, + 0xf4, 0x25, 0x21, 0x83, 0x01, 0x4d, 0xcc, 0xa5, 0x82, 0xe8, 0x83, 0xac, 0xa1, 0xe7, 0x60, 0x75, + 0x6a, 0xc9, 0xe0, 0x1a, 0x28, 0x77, 0x69, 0x2e, 0x96, 0xd9, 0xc0, 0x3c, 0x84, 0x9b, 0x60, 0x5e, + 0xac, 0x99, 0x39, 0x27, 0x6a, 0x32, 0x41, 0xa7, 0x00, 0xde, 0xdf, 0x06, 0x68, 0x82, 0x05, 0xe2, + 0xfb, 0x09, 0x65, 0x4c, 0x11, 0xc6, 0x29, 0xdc, 0x02, 0xba, 0xda, 0x2d, 0xbe, 0xed, 0x06, 0x56, + 0x19, 0x3a, 0x07, 0xeb, 0xf7, 0x26, 0xce, 0x2d, 0xc5, 0x58, 0x05, 0x64, 0x09, 0xcb, 0x04, 0x3e, + 0x06, 0x6b, 0x5e, 0xdc, 0xe7, 0x53, 0x49, 0xdd, 0xb1, 0x8b, 0xbc, 0xd3, 0xea, 0xb8, 0x7e, 0x24, + 0xcb, 0xa8, 0x7b, 0x47, 0x9d, 0x0c, 0x19, 0x6e, 0x83, 0x45, 0x39, 0xd8, 0xd0, 0x57, 0xe0, 0x05, + 0x91, 0xbf, 0xf1, 0xff, 0x01, 0xcd, 0x1b, 0x74, 0x99, 0x84, 0x66, 0x59, 0x00, 0x78, 0x88, 0x8e, + 0xc0, 0xc6, 0x03, 0x93, 0x86, 0x10, 0x54, 0xf8, 0x04, 0x55, 0x23, 0x44, 0xcc, 0xbb, 0x10, 0xd0, + 0xb0, 0x13, 0xa4, 0x82, 0x5e, 0xc1, 0x2a, 0x73, 0x4e, 0xae, 0x46, 0x96, 0x76, 0x3d, 0xb2, 0xb4, + 0x5f, 0x23, 0x4b, 0xfb, 0x7e, 0x63, 0x95, 0xae, 0x6f, 0xac, 0xd2, 0xcf, 0x1b, 0xab, 0xf4, 0xe9, + 0x49, 0x27, 0x4c, 0x83, 0xcb, 0x76, 0xc3, 0x8b, 0xa3, 0x66, 0xd8, 0x0f, 0xd3, 0x90, 0x3c, 0xed, + 0x91, 0x36, 0x6b, 0x8e, 0xdf, 0xa8, 0xaf, 0xe2, 0x95, 0x12, 0x4f, 0x54, 0x5b, 0x17, 0x6f, 0xd4, + 0xe1, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x42, 0x40, 0x76, 0xad, 0x05, 0x05, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -475,6 +484,13 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Erc20Wrapper) > 0 { + i -= len(m.Erc20Wrapper) + copy(dAtA[i:], m.Erc20Wrapper) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Erc20Wrapper))) + i-- + dAtA[i] = 0x4a + } if len(m.Erc20Factory) > 0 { i -= len(m.Erc20Factory) copy(dAtA[i:], m.Erc20Factory) @@ -825,6 +841,10 @@ func (m *GenesisState) Size() (n int) { if l > 0 { n += 1 + l + sovGenesis(uint64(l)) } + l = len(m.Erc20Wrapper) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } return n } @@ -1222,6 +1242,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { m.Erc20Factory = []byte{} } iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20Wrapper", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20Wrapper = append(m.Erc20Wrapper[:0], dAtA[iNdEx:postIndex]...) + if m.Erc20Wrapper == nil { + m.Erc20Wrapper = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index ae1af14..8c6aa2b 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -42,6 +42,7 @@ var ( ParamsKey = []byte{0x51} // key of parameters for module x/evm ERC20FactoryAddrKey = []byte{0x61} // key of erc20 factory contract address + ERC20WrapperAddrKey = []byte{0x62} // key of erc20 wrapper contract address ) // ContextKey type for context key diff --git a/x/evm/types/query.pb.go b/x/evm/types/query.pb.go index 7aeda17..e4854ca 100644 --- a/x/evm/types/query.pb.go +++ b/x/evm/types/query.pb.go @@ -270,6 +270,84 @@ func (m *QueryERC20FactoryResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryERC20FactoryResponse proto.InternalMessageInfo +// QueryERC20WrapperRequest is the request type for the Query/ERC20Wrapper RPC +// method +type QueryERC20WrapperRequest struct { +} + +func (m *QueryERC20WrapperRequest) Reset() { *m = QueryERC20WrapperRequest{} } +func (m *QueryERC20WrapperRequest) String() string { return proto.CompactTextString(m) } +func (*QueryERC20WrapperRequest) ProtoMessage() {} +func (*QueryERC20WrapperRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2bf9e0bee7cfd1a4, []int{6} +} +func (m *QueryERC20WrapperRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryERC20WrapperRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryERC20WrapperRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryERC20WrapperRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryERC20WrapperRequest.Merge(m, src) +} +func (m *QueryERC20WrapperRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryERC20WrapperRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryERC20WrapperRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryERC20WrapperRequest proto.InternalMessageInfo + +// QueryERC20WrapperResponse is the response type for the Query/ERC20Wrapper RPC +// method +type QueryERC20WrapperResponse struct { + // 0x prefixed hex address + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *QueryERC20WrapperResponse) Reset() { *m = QueryERC20WrapperResponse{} } +func (m *QueryERC20WrapperResponse) String() string { return proto.CompactTextString(m) } +func (*QueryERC20WrapperResponse) ProtoMessage() {} +func (*QueryERC20WrapperResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2bf9e0bee7cfd1a4, []int{7} +} +func (m *QueryERC20WrapperResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryERC20WrapperResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryERC20WrapperResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryERC20WrapperResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryERC20WrapperResponse.Merge(m, src) +} +func (m *QueryERC20WrapperResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryERC20WrapperResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryERC20WrapperResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryERC20WrapperResponse proto.InternalMessageInfo + // QueryContractAddrByDenomRequest is the request type for the Query/ContractAddrByDenom RPC // method type QueryContractAddrByDenomRequest struct { @@ -280,7 +358,7 @@ func (m *QueryContractAddrByDenomRequest) Reset() { *m = QueryContractAd func (m *QueryContractAddrByDenomRequest) String() string { return proto.CompactTextString(m) } func (*QueryContractAddrByDenomRequest) ProtoMessage() {} func (*QueryContractAddrByDenomRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{6} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{8} } func (m *QueryContractAddrByDenomRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -320,7 +398,7 @@ func (m *QueryContractAddrByDenomResponse) Reset() { *m = QueryContractA func (m *QueryContractAddrByDenomResponse) String() string { return proto.CompactTextString(m) } func (*QueryContractAddrByDenomResponse) ProtoMessage() {} func (*QueryContractAddrByDenomResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{7} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{9} } func (m *QueryContractAddrByDenomResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -360,7 +438,7 @@ func (m *QueryDenomRequest) Reset() { *m = QueryDenomRequest{} } func (m *QueryDenomRequest) String() string { return proto.CompactTextString(m) } func (*QueryDenomRequest) ProtoMessage() {} func (*QueryDenomRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{8} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{10} } func (m *QueryDenomRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -399,7 +477,7 @@ func (m *QueryDenomResponse) Reset() { *m = QueryDenomResponse{} } func (m *QueryDenomResponse) String() string { return proto.CompactTextString(m) } func (*QueryDenomResponse) ProtoMessage() {} func (*QueryDenomResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{9} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{11} } func (m *QueryDenomResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -448,7 +526,7 @@ func (m *QueryCallRequest) Reset() { *m = QueryCallRequest{} } func (m *QueryCallRequest) String() string { return proto.CompactTextString(m) } func (*QueryCallRequest) ProtoMessage() {} func (*QueryCallRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{10} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{12} } func (m *QueryCallRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -493,7 +571,7 @@ func (m *TraceOptions) Reset() { *m = TraceOptions{} } func (m *TraceOptions) String() string { return proto.CompactTextString(m) } func (*TraceOptions) ProtoMessage() {} func (*TraceOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{11} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{13} } func (m *TraceOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -537,7 +615,7 @@ func (m *QueryCallResponse) Reset() { *m = QueryCallResponse{} } func (m *QueryCallResponse) String() string { return proto.CompactTextString(m) } func (*QueryCallResponse) ProtoMessage() {} func (*QueryCallResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{12} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{14} } func (m *QueryCallResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -574,7 +652,7 @@ func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryParamsRequest) ProtoMessage() {} func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{13} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{15} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -613,7 +691,7 @@ func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryParamsResponse) ProtoMessage() {} func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_2bf9e0bee7cfd1a4, []int{14} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{16} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -649,6 +727,8 @@ func init() { proto.RegisterType((*QueryStateResponse)(nil), "minievm.evm.v1.QueryStateResponse") proto.RegisterType((*QueryERC20FactoryRequest)(nil), "minievm.evm.v1.QueryERC20FactoryRequest") proto.RegisterType((*QueryERC20FactoryResponse)(nil), "minievm.evm.v1.QueryERC20FactoryResponse") + proto.RegisterType((*QueryERC20WrapperRequest)(nil), "minievm.evm.v1.QueryERC20WrapperRequest") + proto.RegisterType((*QueryERC20WrapperResponse)(nil), "minievm.evm.v1.QueryERC20WrapperResponse") proto.RegisterType((*QueryContractAddrByDenomRequest)(nil), "minievm.evm.v1.QueryContractAddrByDenomRequest") proto.RegisterType((*QueryContractAddrByDenomResponse)(nil), "minievm.evm.v1.QueryContractAddrByDenomResponse") proto.RegisterType((*QueryDenomRequest)(nil), "minievm.evm.v1.QueryDenomRequest") @@ -663,68 +743,70 @@ func init() { func init() { proto.RegisterFile("minievm/evm/v1/query.proto", fileDescriptor_2bf9e0bee7cfd1a4) } var fileDescriptor_2bf9e0bee7cfd1a4 = []byte{ - // 968 bytes of a gzipped FileDescriptorProto + // 1003 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x41, 0x6f, 0x1b, 0x45, - 0x14, 0xf6, 0x26, 0x76, 0xe2, 0x3c, 0xa7, 0x55, 0x3a, 0x31, 0x91, 0xb3, 0x2a, 0x6b, 0x77, 0x0b, - 0xd4, 0x8d, 0xc8, 0x6e, 0x6a, 0x2a, 0xb5, 0x2a, 0xa7, 0xba, 0x05, 0x04, 0x14, 0x01, 0x5b, 0x4e, - 0x5c, 0xac, 0x89, 0x77, 0xd8, 0xac, 0xe2, 0xdd, 0x71, 0x76, 0xc6, 0x01, 0x53, 0x95, 0x03, 0xe2, - 0x07, 0x20, 0xc1, 0x8d, 0x0b, 0x07, 0x0e, 0xe5, 0xc6, 0x8d, 0xbf, 0x90, 0x63, 0x25, 0x2e, 0x88, - 0x43, 0x05, 0x0e, 0x12, 0xfc, 0x0c, 0x34, 0x6f, 0x67, 0x5b, 0x7b, 0xbd, 0x8e, 0xc2, 0xc1, 0xd6, - 0xbc, 0x37, 0xdf, 0xbc, 0xef, 0x7b, 0xef, 0xcd, 0x3c, 0x2d, 0x98, 0x51, 0x18, 0x87, 0xec, 0x38, - 0x72, 0xd5, 0xef, 0xf8, 0x86, 0x7b, 0x34, 0x62, 0xc9, 0xd8, 0x19, 0x26, 0x5c, 0x72, 0x72, 0x51, - 0xef, 0x39, 0xea, 0x77, 0x7c, 0xc3, 0xbc, 0x44, 0xa3, 0x30, 0xe6, 0x2e, 0xfe, 0xa7, 0x10, 0xb3, - 0x1e, 0xf0, 0x80, 0xe3, 0xd2, 0x55, 0x2b, 0xed, 0xbd, 0x1c, 0x70, 0x1e, 0x0c, 0x98, 0x4b, 0x87, - 0xa1, 0x4b, 0xe3, 0x98, 0x4b, 0x2a, 0x43, 0x1e, 0x0b, 0xbd, 0x9b, 0xa7, 0x94, 0xe3, 0x21, 0xd3, - 0x7b, 0xf6, 0x2d, 0xd8, 0xf8, 0x58, 0x29, 0xb8, 0xc7, 0x7d, 0xe6, 0xb1, 0xa3, 0x11, 0x13, 0x92, - 0x5c, 0x85, 0x0b, 0x7d, 0x1e, 0xcb, 0x84, 0xf6, 0x65, 0x8f, 0xfa, 0x7e, 0xd2, 0x30, 0x5a, 0x46, - 0x7b, 0xcd, 0x5b, 0xcf, 0x9c, 0x77, 0x7d, 0x3f, 0xb1, 0x77, 0xe1, 0xd2, 0xd4, 0x41, 0x31, 0xe4, - 0xb1, 0x60, 0x84, 0x40, 0xb9, 0xcf, 0x7d, 0xa6, 0x0f, 0xe0, 0xfa, 0x4e, 0xf9, 0xdf, 0x1f, 0x9b, - 0x86, 0xfd, 0x9e, 0x86, 0x3f, 0x94, 0x54, 0xfe, 0x2f, 0x22, 0xb2, 0x01, 0xcb, 0x87, 0x6c, 0xdc, - 0x58, 0xc2, 0x2d, 0xb5, 0xb4, 0xf7, 0x80, 0x4c, 0xc7, 0xd2, 0xdc, 0x75, 0xa8, 0x1c, 0xd3, 0xc1, - 0x28, 0x23, 0x4f, 0x0d, 0xcd, 0x6e, 0x42, 0x03, 0x4f, 0xbc, 0xe5, 0xdd, 0xeb, 0xec, 0xbd, 0x4d, - 0xfb, 0x92, 0x27, 0x63, 0x2d, 0xc2, 0x7e, 0x13, 0xb6, 0x0b, 0xf6, 0x74, 0xd0, 0x06, 0xac, 0x2a, - 0x61, 0x4c, 0x08, 0x1d, 0x36, 0x33, 0x75, 0xe0, 0x5b, 0xd0, 0xd4, 0x55, 0x78, 0xa1, 0xb8, 0x3b, - 0xbe, 0xcf, 0x62, 0x1e, 0x65, 0x49, 0xd6, 0xa1, 0xe2, 0x2b, 0x3b, 0xd3, 0x85, 0x86, 0xdd, 0x85, - 0xd6, 0xe2, 0x83, 0xe7, 0x24, 0xbf, 0xad, 0x6b, 0x3a, 0x43, 0x77, 0xae, 0xe6, 0x65, 0x15, 0x9c, - 0xe5, 0x2b, 0x54, 0xaa, 0xb9, 0x26, 0x46, 0x76, 0x51, 0xe8, 0x60, 0x90, 0x71, 0x6d, 0xc1, 0x8a, - 0x60, 0xb1, 0xcf, 0x32, 0x12, 0x6d, 0xcd, 0x6b, 0x58, 0x2a, 0xe8, 0x6b, 0x1d, 0x2a, 0x61, 0x3c, - 0x1c, 0xc9, 0xc6, 0x72, 0xca, 0x86, 0x06, 0xb9, 0x9d, 0x75, 0xb1, 0xac, 0xbc, 0x5d, 0xfb, 0xe4, - 0x59, 0xb3, 0xf4, 0xc7, 0xb3, 0xe6, 0x4b, 0x7d, 0x2e, 0x22, 0x2e, 0x84, 0x7f, 0xe8, 0x84, 0xdc, - 0x8d, 0xa8, 0x3c, 0x70, 0xde, 0x8d, 0xe5, 0x93, 0x7f, 0x7e, 0xd9, 0x31, 0x74, 0xa7, 0xc9, 0x5d, - 0xb8, 0xa0, 0x82, 0xb3, 0x1e, 0x1f, 0xe2, 0xe5, 0x6f, 0x54, 0x5a, 0x46, 0xbb, 0xd6, 0xb9, 0xec, - 0xcc, 0x3e, 0x2a, 0xe7, 0x13, 0x05, 0xfa, 0x30, 0xc5, 0x78, 0xeb, 0x72, 0xca, 0xb2, 0x7f, 0x30, - 0x60, 0x7d, 0x7a, 0x9b, 0x34, 0xa1, 0xf6, 0x79, 0x28, 0x0f, 0x7a, 0x11, 0x8b, 0x78, 0x32, 0xc6, - 0x2c, 0xab, 0x1e, 0x28, 0xd7, 0x07, 0xe8, 0x21, 0x2f, 0x03, 0x5a, 0x3d, 0x21, 0x69, 0xff, 0x10, - 0xd3, 0xac, 0x7a, 0x6b, 0xca, 0xf3, 0x50, 0x39, 0xc8, 0x15, 0x58, 0xd7, 0xdb, 0x3c, 0xa1, 0x01, - 0xc3, 0x54, 0xab, 0x5e, 0x2d, 0x05, 0xa0, 0x8b, 0xb4, 0x61, 0x03, 0x21, 0x09, 0x93, 0xa3, 0x24, - 0xee, 0xf9, 0x54, 0x52, 0xcc, 0xbd, 0xea, 0x5d, 0x54, 0x7e, 0x0f, 0xdd, 0xf7, 0xa9, 0xa4, 0xf6, - 0xaf, 0x46, 0xf6, 0xe4, 0xb0, 0x05, 0xba, 0x69, 0x26, 0x54, 0x13, 0xbd, 0xd6, 0x5d, 0x78, 0x6e, - 0x93, 0x6d, 0xa8, 0x8e, 0x04, 0xf3, 0x7b, 0x01, 0x15, 0xa8, 0xad, 0xec, 0xad, 0x2a, 0xfb, 0x1d, - 0x2a, 0x48, 0x07, 0xca, 0x03, 0x1e, 0x88, 0xc6, 0x72, 0x6b, 0xb9, 0x5d, 0xeb, 0x6c, 0xe6, 0x8b, - 0xf4, 0x80, 0x07, 0xdd, 0x35, 0x55, 0xfb, 0xb4, 0xc4, 0x88, 0x55, 0xd9, 0xe8, 0x0a, 0x8f, 0xa4, - 0x6a, 0x1c, 0xb6, 0xc8, 0xab, 0xa5, 0x25, 0x44, 0x97, 0x6a, 0x2a, 0x4b, 0x12, 0x9e, 0x60, 0xf1, - 0xd7, 0xbc, 0xd4, 0xb0, 0xeb, 0xfa, 0xba, 0x7d, 0x44, 0x13, 0x1a, 0x89, 0xec, 0xe1, 0xbd, 0x0f, - 0x9b, 0x33, 0x5e, 0x2d, 0xfa, 0x26, 0xac, 0x0c, 0xd1, 0x83, 0xe9, 0xd4, 0x3a, 0x5b, 0x79, 0x6d, - 0x29, 0xbe, 0x5b, 0x56, 0xf2, 0x3c, 0x8d, 0xed, 0xfc, 0xbc, 0x0a, 0x15, 0x8c, 0x46, 0xbe, 0x84, - 0xb2, 0x9a, 0x49, 0xa4, 0x95, 0x3f, 0x97, 0x9f, 0x73, 0xe6, 0x95, 0x33, 0x10, 0xa9, 0x18, 0x7b, - 0xf7, 0xeb, 0xdf, 0xfe, 0xfe, 0x6e, 0xe9, 0x1a, 0x79, 0xd5, 0xcd, 0xcd, 0x50, 0x35, 0xda, 0x84, - 0xfb, 0x68, 0xe6, 0x9a, 0x3f, 0x26, 0xdf, 0x18, 0x50, 0xc1, 0xa9, 0x44, 0x8a, 0x63, 0x4f, 0x4f, - 0x3f, 0xd3, 0x3e, 0x0b, 0xa2, 0xf9, 0x6f, 0x22, 0xbf, 0x43, 0x5e, 0xcf, 0xf3, 0x0b, 0x05, 0x9b, - 0x13, 0xe0, 0x3e, 0x3a, 0x64, 0xe3, 0xc7, 0xe4, 0x7b, 0x03, 0xd6, 0xa7, 0xc7, 0x19, 0x69, 0x17, - 0x52, 0x15, 0x4c, 0x43, 0xf3, 0xfa, 0x39, 0x90, 0x5a, 0x9b, 0x8b, 0xda, 0xae, 0x93, 0x6b, 0xf3, - 0xb5, 0x49, 0x35, 0x09, 0x97, 0x25, 0xfd, 0xce, 0x5e, 0xef, 0x33, 0xad, 0xe2, 0x27, 0x03, 0x36, - 0x0b, 0xe6, 0x1d, 0x71, 0x17, 0xf4, 0x61, 0xd1, 0x48, 0x35, 0xf7, 0xce, 0x7f, 0x40, 0x6b, 0xdd, - 0x41, 0xad, 0xaf, 0x10, 0x7b, 0xb1, 0xd6, 0xfd, 0x71, 0x0f, 0x07, 0x1e, 0xf9, 0x0a, 0x2a, 0xa9, - 0xae, 0xe2, 0x1e, 0xce, 0x28, 0xb1, 0xcf, 0x82, 0x68, 0x6e, 0x07, 0xb9, 0xdb, 0xe4, 0xb5, 0x3c, - 0x37, 0xd2, 0xcd, 0x5f, 0xa2, 0x01, 0x94, 0xd5, 0x0b, 0x5f, 0x74, 0x81, 0x5f, 0xcc, 0xdf, 0x45, - 0x17, 0x78, 0x6a, 0x3c, 0xd8, 0x4d, 0x24, 0xdf, 0xbe, 0x63, 0xec, 0xd8, 0xf5, 0xb9, 0xdc, 0x15, - 0xcb, 0x11, 0xac, 0xa4, 0x0f, 0x8a, 0x14, 0xe7, 0x32, 0xf3, 0x66, 0xcd, 0xab, 0x67, 0x62, 0x34, - 0xa7, 0x85, 0x9c, 0x0d, 0xb2, 0x95, 0x27, 0x4c, 0xdf, 0x6a, 0xf7, 0xc1, 0xc9, 0x5f, 0x56, 0xe9, - 0xc9, 0xc4, 0x2a, 0x9d, 0x4c, 0x2c, 0xe3, 0xe9, 0xc4, 0x32, 0xfe, 0x9c, 0x58, 0xc6, 0xb7, 0xa7, - 0x56, 0xe9, 0xe9, 0xa9, 0x55, 0xfa, 0xfd, 0xd4, 0x2a, 0x7d, 0xba, 0x13, 0x84, 0xf2, 0x60, 0xb4, - 0xef, 0xf4, 0x79, 0xe4, 0x86, 0x71, 0x28, 0x43, 0xba, 0x3b, 0xa0, 0xfb, 0xe2, 0x79, 0xbc, 0x2f, - 0x30, 0x22, 0x7e, 0xc7, 0xec, 0xaf, 0xe0, 0x87, 0xcc, 0x1b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, - 0xec, 0xe7, 0xcf, 0xd0, 0x59, 0x09, 0x00, 0x00, + 0x14, 0xf6, 0x26, 0x76, 0xea, 0x3c, 0xbb, 0x55, 0x3a, 0x31, 0x91, 0xb3, 0x2a, 0xb6, 0xbb, 0x05, + 0xea, 0x46, 0xc4, 0x9b, 0x9a, 0x4a, 0xad, 0xca, 0xa9, 0x6e, 0x01, 0x01, 0x45, 0xc0, 0x16, 0x09, + 0x89, 0x8b, 0x35, 0xf1, 0x0e, 0xce, 0x2a, 0xde, 0x9d, 0xcd, 0xce, 0x38, 0xc5, 0x54, 0xe5, 0x80, + 0xf8, 0x01, 0x48, 0x70, 0xe3, 0xc2, 0x81, 0x43, 0x8f, 0xdc, 0xb8, 0x72, 0xcc, 0xb1, 0x12, 0x17, + 0xc4, 0xa1, 0x02, 0x07, 0x09, 0x7e, 0x06, 0x9a, 0xb7, 0xb3, 0x89, 0xbd, 0x5e, 0x5b, 0xe6, 0xe0, + 0x68, 0xde, 0x9b, 0x37, 0xef, 0xfb, 0xde, 0x9b, 0x37, 0x5f, 0x16, 0x4c, 0xdf, 0x0b, 0x3c, 0x76, + 0xec, 0xdb, 0xea, 0x77, 0x7c, 0xd3, 0x3e, 0x1a, 0xb2, 0x68, 0xd4, 0x0a, 0x23, 0x2e, 0x39, 0xb9, + 0xa4, 0xf7, 0x5a, 0xea, 0x77, 0x7c, 0xd3, 0xbc, 0x4c, 0x7d, 0x2f, 0xe0, 0x36, 0xfe, 0x8d, 0x43, + 0xcc, 0x4a, 0x9f, 0xf7, 0x39, 0x2e, 0x6d, 0xb5, 0xd2, 0xde, 0x2b, 0x7d, 0xce, 0xfb, 0x03, 0x66, + 0xd3, 0xd0, 0xb3, 0x69, 0x10, 0x70, 0x49, 0xa5, 0xc7, 0x03, 0xa1, 0x77, 0xd3, 0x90, 0x72, 0x14, + 0x32, 0xbd, 0x67, 0xdd, 0x86, 0x8d, 0x8f, 0x15, 0x83, 0xfb, 0xdc, 0x65, 0x0e, 0x3b, 0x1a, 0x32, + 0x21, 0xc9, 0x35, 0xb8, 0xd8, 0xe3, 0x81, 0x8c, 0x68, 0x4f, 0x76, 0xa9, 0xeb, 0x46, 0x55, 0xa3, + 0x61, 0x34, 0xd7, 0x9d, 0x72, 0xe2, 0xbc, 0xe7, 0xba, 0x91, 0xb5, 0x0b, 0x97, 0x27, 0x0e, 0x8a, + 0x90, 0x07, 0x82, 0x11, 0x02, 0xf9, 0x1e, 0x77, 0x99, 0x3e, 0x80, 0xeb, 0xbb, 0xf9, 0x7f, 0x7f, + 0xac, 0x1b, 0xd6, 0x7b, 0x3a, 0xfc, 0x91, 0xa4, 0xf2, 0x7f, 0x01, 0x91, 0x0d, 0x58, 0x3d, 0x64, + 0xa3, 0xea, 0x0a, 0x6e, 0xa9, 0xa5, 0xb5, 0x07, 0x64, 0x32, 0x97, 0xc6, 0xae, 0x40, 0xe1, 0x98, + 0x0e, 0x86, 0x09, 0x78, 0x6c, 0x68, 0x74, 0x13, 0xaa, 0x78, 0xe2, 0x2d, 0xe7, 0x7e, 0x7b, 0xef, + 0x6d, 0xda, 0x93, 0x3c, 0x1a, 0x69, 0x12, 0xd6, 0x9b, 0xb0, 0x9d, 0xb1, 0xa7, 0x93, 0x56, 0xe1, + 0x82, 0x22, 0xc6, 0x84, 0xd0, 0x69, 0x13, 0x33, 0x2b, 0xf1, 0xa7, 0x11, 0x0d, 0x43, 0x16, 0x65, + 0x26, 0x3e, 0xdb, 0x5b, 0x32, 0xf1, 0x6d, 0xa8, 0xeb, 0xf6, 0x9e, 0xb7, 0xa2, 0x33, 0x7a, 0xc0, + 0x02, 0xee, 0x27, 0xdd, 0xab, 0x40, 0xc1, 0x55, 0x76, 0x52, 0x30, 0x1a, 0x56, 0x07, 0x1a, 0xf3, + 0x0f, 0x2e, 0x09, 0x7e, 0x47, 0x5f, 0xd6, 0x14, 0xdc, 0x52, 0x53, 0x91, 0x5c, 0xcd, 0x34, 0x5e, + 0x26, 0x53, 0x8d, 0x35, 0x36, 0x92, 0x09, 0xa4, 0x83, 0x41, 0x82, 0xb5, 0x05, 0x6b, 0x82, 0x05, + 0x2e, 0x4b, 0x40, 0xb4, 0x35, 0xcb, 0x61, 0x25, 0x63, 0x60, 0x2a, 0x50, 0xf0, 0x82, 0x70, 0x28, + 0xab, 0xab, 0x31, 0x1a, 0x1a, 0xe4, 0x4e, 0x32, 0x1e, 0x79, 0xe5, 0xed, 0x58, 0x27, 0x2f, 0xea, + 0xb9, 0x3f, 0x5e, 0xd4, 0x5f, 0xea, 0x71, 0xe1, 0x73, 0x21, 0xdc, 0xc3, 0x96, 0xc7, 0x6d, 0x9f, + 0xca, 0x83, 0xd6, 0xbb, 0x81, 0x7c, 0xf6, 0xcf, 0xcf, 0x3b, 0x86, 0x1e, 0x21, 0x72, 0x0f, 0x2e, + 0xaa, 0xe4, 0xac, 0xcb, 0x43, 0x7c, 0x55, 0xd5, 0x42, 0xc3, 0x68, 0x96, 0xda, 0x57, 0x5a, 0xd3, + 0xaf, 0xb5, 0xf5, 0x89, 0x0a, 0xfa, 0x30, 0x8e, 0x71, 0xca, 0x72, 0xc2, 0xb2, 0x7e, 0x30, 0xa0, + 0x3c, 0xb9, 0x4d, 0xea, 0x50, 0x7a, 0xec, 0xc9, 0x83, 0xae, 0xcf, 0x7c, 0x1e, 0x8d, 0xb0, 0xca, + 0xa2, 0x03, 0xca, 0xf5, 0x01, 0x7a, 0xc8, 0xcb, 0x80, 0x56, 0x57, 0x48, 0xda, 0x3b, 0xc4, 0x32, + 0x8b, 0xce, 0xba, 0xf2, 0x3c, 0x52, 0x0e, 0x72, 0x15, 0xca, 0x7a, 0x9b, 0x47, 0xb4, 0xcf, 0xb0, + 0xd4, 0xa2, 0x53, 0x8a, 0x03, 0xd0, 0x45, 0x9a, 0xb0, 0x81, 0x21, 0x11, 0x93, 0xc3, 0x28, 0xe8, + 0xba, 0x54, 0x52, 0xac, 0xbd, 0xe8, 0x5c, 0x52, 0x7e, 0x07, 0xdd, 0x0f, 0xa8, 0xa4, 0xd6, 0x2f, + 0x46, 0xf2, 0x96, 0xf1, 0x0a, 0xf4, 0xa5, 0x99, 0x50, 0x8c, 0xf4, 0x5a, 0xdf, 0xc2, 0x99, 0x4d, + 0xb6, 0xa1, 0x38, 0x14, 0xcc, 0xed, 0xf6, 0xa9, 0x40, 0x6e, 0x79, 0xe7, 0x82, 0xb2, 0xdf, 0xa1, + 0x82, 0xb4, 0x21, 0x3f, 0xe0, 0x7d, 0x51, 0x5d, 0x6d, 0xac, 0x36, 0x4b, 0xed, 0xcd, 0x74, 0x93, + 0x1e, 0xf2, 0x7e, 0x67, 0x5d, 0xf5, 0x3e, 0x6e, 0x31, 0xc6, 0xaa, 0x6a, 0x74, 0x87, 0x87, 0x52, + 0x5d, 0x1c, 0x5e, 0x91, 0x53, 0x8a, 0x5b, 0x88, 0x2e, 0x75, 0xa9, 0x2c, 0x8a, 0x78, 0x84, 0xcd, + 0x5f, 0x77, 0x62, 0xc3, 0xaa, 0xe8, 0x71, 0xfb, 0x88, 0x46, 0xd4, 0x17, 0xc9, 0xc3, 0x7b, 0x1f, + 0x36, 0xa7, 0xbc, 0x9a, 0xf4, 0x2d, 0x58, 0x0b, 0xd1, 0x83, 0xe5, 0x94, 0xda, 0x5b, 0x69, 0x6e, + 0x71, 0x7c, 0x27, 0xaf, 0xe8, 0x39, 0x3a, 0xb6, 0xfd, 0x6b, 0x11, 0x0a, 0x98, 0x8d, 0x7c, 0x09, + 0x79, 0x25, 0x76, 0xa4, 0x91, 0x3e, 0x97, 0x16, 0x50, 0xf3, 0xea, 0x82, 0x88, 0x98, 0x8c, 0xb5, + 0xfb, 0xf5, 0x6f, 0x7f, 0x7f, 0xb7, 0x72, 0x9d, 0xbc, 0x6a, 0xa7, 0xc4, 0x59, 0x69, 0xa6, 0xb0, + 0x9f, 0x4c, 0x8d, 0xf9, 0x53, 0xf2, 0x8d, 0x01, 0x05, 0x94, 0x3b, 0x92, 0x9d, 0x7b, 0x52, 0x56, + 0x4d, 0x6b, 0x51, 0x88, 0xc6, 0xbf, 0x85, 0xf8, 0x2d, 0xf2, 0x7a, 0x1a, 0x5f, 0xa8, 0xb0, 0x19, + 0x02, 0xf6, 0x93, 0x43, 0x36, 0x7a, 0x4a, 0xbe, 0x37, 0xa0, 0x3c, 0xa9, 0x93, 0xa4, 0x99, 0x09, + 0x95, 0x21, 0xb3, 0xe6, 0x8d, 0x25, 0x22, 0x35, 0x37, 0x1b, 0xb9, 0xdd, 0x20, 0xd7, 0x67, 0x7b, + 0x13, 0x73, 0x12, 0x36, 0x8b, 0x7a, 0xed, 0xbd, 0xee, 0xe7, 0x9a, 0xc5, 0x19, 0x2d, 0xad, 0xb2, + 0x8b, 0x68, 0x4d, 0x8b, 0xf4, 0x22, 0x5a, 0x29, 0xc9, 0x5e, 0x9e, 0xd6, 0x63, 0xcd, 0xe2, 0x27, + 0x03, 0x36, 0x33, 0x64, 0x98, 0xd8, 0x73, 0xc6, 0x63, 0x9e, 0xd2, 0x9b, 0x7b, 0xcb, 0x1f, 0xd0, + 0x5c, 0x77, 0x90, 0xeb, 0x2b, 0xc4, 0x9a, 0xcf, 0x75, 0x7f, 0xd4, 0x45, 0x1d, 0x26, 0x5f, 0x41, + 0x21, 0xe6, 0x95, 0x3d, 0x5a, 0x53, 0x4c, 0xac, 0x45, 0x21, 0x1a, 0xbb, 0x85, 0xd8, 0x4d, 0xf2, + 0x5a, 0x1a, 0x1b, 0xe1, 0x66, 0x67, 0x7b, 0x00, 0x79, 0x25, 0x3c, 0xf3, 0xde, 0xd5, 0xf9, 0xbf, + 0x85, 0x79, 0xef, 0x6a, 0x42, 0xb5, 0xac, 0x3a, 0x82, 0x6f, 0xdf, 0x35, 0x76, 0xac, 0xca, 0x4c, + 0xed, 0x0a, 0xe5, 0x08, 0xd6, 0xe2, 0x77, 0x4e, 0xb2, 0x6b, 0x99, 0x92, 0x12, 0xf3, 0xda, 0xc2, + 0x18, 0x8d, 0x59, 0x43, 0xcc, 0x2a, 0xd9, 0x4a, 0x03, 0xc6, 0x12, 0xd2, 0x79, 0x78, 0xf2, 0x57, + 0x2d, 0xf7, 0x6c, 0x5c, 0xcb, 0x9d, 0x8c, 0x6b, 0xc6, 0xf3, 0x71, 0xcd, 0xf8, 0x73, 0x5c, 0x33, + 0xbe, 0x3d, 0xad, 0xe5, 0x9e, 0x9f, 0xd6, 0x72, 0xbf, 0x9f, 0xd6, 0x72, 0x9f, 0xed, 0xf4, 0x3d, + 0x79, 0x30, 0xdc, 0x6f, 0xf5, 0xb8, 0x6f, 0x7b, 0x81, 0x27, 0x3d, 0xba, 0x3b, 0xa0, 0xfb, 0xe2, + 0x2c, 0xdf, 0x17, 0x98, 0x11, 0xbf, 0xdb, 0xf6, 0xd7, 0xf0, 0xc3, 0xed, 0x8d, 0xff, 0x02, 0x00, + 0x00, 0xff, 0xff, 0x93, 0x38, 0xd1, 0x8c, 0x49, 0x0a, 0x00, 0x00, } func (this *QueryCodeResponse) Equal(that interface{}) bool { @@ -799,6 +881,30 @@ func (this *QueryERC20FactoryResponse) Equal(that interface{}) bool { } return true } +func (this *QueryERC20WrapperResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryERC20WrapperResponse) + if !ok { + that2, ok := that.(QueryERC20WrapperResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Address != that1.Address { + return false + } + return true +} func (this *QueryContractAddrByDenomResponse) Equal(that interface{}) bool { if that == nil { return this == nil @@ -866,6 +972,8 @@ type QueryClient interface { State(ctx context.Context, in *QueryStateRequest, opts ...grpc.CallOption) (*QueryStateResponse, error) // ERC20Factory gets the ERC20Factory contract address. ERC20Factory(ctx context.Context, in *QueryERC20FactoryRequest, opts ...grpc.CallOption) (*QueryERC20FactoryResponse, error) + // ERC20Wrapper gets the ERC20Wrapper contract address. + ERC20Wrapper(ctx context.Context, in *QueryERC20WrapperRequest, opts ...grpc.CallOption) (*QueryERC20WrapperResponse, error) // ContractAddrByDenom gets the contract address by denom. ContractAddrByDenom(ctx context.Context, in *QueryContractAddrByDenomRequest, opts ...grpc.CallOption) (*QueryContractAddrByDenomResponse, error) // Denom gets the denom of the given contract address. @@ -911,6 +1019,15 @@ func (c *queryClient) ERC20Factory(ctx context.Context, in *QueryERC20FactoryReq return out, nil } +func (c *queryClient) ERC20Wrapper(ctx context.Context, in *QueryERC20WrapperRequest, opts ...grpc.CallOption) (*QueryERC20WrapperResponse, error) { + out := new(QueryERC20WrapperResponse) + err := c.cc.Invoke(ctx, "/minievm.evm.v1.Query/ERC20Wrapper", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) ContractAddrByDenom(ctx context.Context, in *QueryContractAddrByDenomRequest, opts ...grpc.CallOption) (*QueryContractAddrByDenomResponse, error) { out := new(QueryContractAddrByDenomResponse) err := c.cc.Invoke(ctx, "/minievm.evm.v1.Query/ContractAddrByDenom", in, out, opts...) @@ -955,6 +1072,8 @@ type QueryServer interface { State(context.Context, *QueryStateRequest) (*QueryStateResponse, error) // ERC20Factory gets the ERC20Factory contract address. ERC20Factory(context.Context, *QueryERC20FactoryRequest) (*QueryERC20FactoryResponse, error) + // ERC20Wrapper gets the ERC20Wrapper contract address. + ERC20Wrapper(context.Context, *QueryERC20WrapperRequest) (*QueryERC20WrapperResponse, error) // ContractAddrByDenom gets the contract address by denom. ContractAddrByDenom(context.Context, *QueryContractAddrByDenomRequest) (*QueryContractAddrByDenomResponse, error) // Denom gets the denom of the given contract address. @@ -978,6 +1097,9 @@ func (*UnimplementedQueryServer) State(ctx context.Context, req *QueryStateReque func (*UnimplementedQueryServer) ERC20Factory(ctx context.Context, req *QueryERC20FactoryRequest) (*QueryERC20FactoryResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ERC20Factory not implemented") } +func (*UnimplementedQueryServer) ERC20Wrapper(ctx context.Context, req *QueryERC20WrapperRequest) (*QueryERC20WrapperResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ERC20Wrapper not implemented") +} func (*UnimplementedQueryServer) ContractAddrByDenom(ctx context.Context, req *QueryContractAddrByDenomRequest) (*QueryContractAddrByDenomResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ContractAddrByDenom not implemented") } @@ -1049,6 +1171,24 @@ func _Query_ERC20Factory_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_ERC20Wrapper_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryERC20WrapperRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ERC20Wrapper(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/minievm.evm.v1.Query/ERC20Wrapper", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ERC20Wrapper(ctx, req.(*QueryERC20WrapperRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_ContractAddrByDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryContractAddrByDenomRequest) if err := dec(in); err != nil { @@ -1137,6 +1277,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "ERC20Factory", Handler: _Query_ERC20Factory_Handler, }, + { + MethodName: "ERC20Wrapper", + Handler: _Query_ERC20Wrapper_Handler, + }, { MethodName: "ContractAddrByDenom", Handler: _Query_ContractAddrByDenom_Handler, @@ -1338,6 +1482,59 @@ func (m *QueryERC20FactoryResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *QueryERC20WrapperRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryERC20WrapperRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryERC20WrapperRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryERC20WrapperResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryERC20WrapperResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryERC20WrapperResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *QueryContractAddrByDenomRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1795,6 +1992,28 @@ func (m *QueryERC20FactoryResponse) Size() (n int) { return n } +func (m *QueryERC20WrapperRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryERC20WrapperResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func (m *QueryContractAddrByDenomRequest) Size() (n int) { if m == nil { return 0 @@ -2443,6 +2662,138 @@ func (m *QueryERC20FactoryResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryERC20WrapperRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryERC20WrapperRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryERC20WrapperRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryERC20WrapperResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryERC20WrapperResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryERC20WrapperResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryContractAddrByDenomRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/evm/types/query.pb.gw.go b/x/evm/types/query.pb.gw.go index f8c3ed5..4c2e106 100644 --- a/x/evm/types/query.pb.gw.go +++ b/x/evm/types/query.pb.gw.go @@ -181,6 +181,24 @@ func local_request_Query_ERC20Factory_0(ctx context.Context, marshaler runtime.M } +func request_Query_ERC20Wrapper_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryERC20WrapperRequest + var metadata runtime.ServerMetadata + + msg, err := client.ERC20Wrapper(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ERC20Wrapper_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryERC20WrapperRequest + var metadata runtime.ServerMetadata + + msg, err := server.ERC20Wrapper(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ContractAddrByDenom_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -398,6 +416,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_ERC20Wrapper_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ERC20Wrapper_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ERC20Wrapper_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_ContractAddrByDenom_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -591,6 +632,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_ERC20Wrapper_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ERC20Wrapper_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ERC20Wrapper_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_ContractAddrByDenom_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -681,6 +742,8 @@ var ( pattern_Query_ERC20Factory_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"minievm", "evm", "v1", "contracts", "erc20_factory"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_ERC20Wrapper_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"minievm", "evm", "v1", "contracts", "erc20_wrapper"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_ContractAddrByDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"minievm", "evm", "v1", "contracts", "by_denom"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Denom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"minievm", "evm", "v1", "denoms", "contract_addr"}, "", runtime.AssumeColonVerbOpt(false))) @@ -697,6 +760,8 @@ var ( forward_Query_ERC20Factory_0 = runtime.ForwardResponseMessage + forward_Query_ERC20Wrapper_0 = runtime.ForwardResponseMessage + forward_Query_ContractAddrByDenom_0 = runtime.ForwardResponseMessage forward_Query_Denom_0 = runtime.ForwardResponseMessage