From 3aab81b726370037c3d40c3a21d408227ecd8f3e Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:13:58 +0900 Subject: [PATCH] add erc20 supports --- app/app.go | 26 +- app/ibc-hooks/README.md | 164 +++ app/ibc-hooks/ack.go | 98 ++ app/ibc-hooks/common_test.go | 398 +++++++ app/ibc-hooks/hooks.go | 84 ++ app/ibc-hooks/message.go | 45 + app/ibc-hooks/receive.go | 135 +++ app/ibc-hooks/receive_test.go | 103 ++ app/ibc-hooks/timeout.go | 97 ++ app/ibc-hooks/util.go | 134 +++ app/ibc-hooks/util_test.go | 106 ++ app/ibc-middleware/util_test.go | 2 +- app/upgrade.go | 2 +- go.mod | 67 +- go.sum | 138 ++- proto/buf.lock | 30 +- proto/buf.yaml | 12 +- proto/minievm/bank/v1/tx.proto | 36 + proto/minievm/evm/v1/auth.proto | 17 + proto/minievm/evm/v1/genesis.proto | 23 +- proto/minievm/evm/v1/query.proto | 49 +- proto/minievm/evm/v1/tx.proto | 16 +- proto/minievm/evm/v1/types.proto | 4 +- scripts/contractsgen.sh | 20 +- x/bank/autocli.go | 118 ++ x/bank/keeper/common_test.go | 319 ++++++ x/bank/keeper/custom_msg_server.go | 38 + x/bank/keeper/custom_msg_server_test.go | 41 + x/bank/keeper/genesis.go | 61 + x/bank/keeper/genesis_test.go | 112 ++ x/bank/keeper/grpc_query.go | 266 +++++ x/bank/keeper/grpc_query_test.go | 150 +++ x/bank/keeper/keeper.go | 376 ++++++ x/bank/keeper/keeper_test.go | 400 +++++++ x/bank/keeper/msg_server.go | 141 +++ x/bank/keeper/msg_server_test.go | 279 +++++ x/bank/keeper/send.go | 335 ++++++ x/bank/keeper/view.go | 197 ++++ x/bank/module.go | 144 +++ x/bank/types/codec.go | 26 + x/bank/types/tx.pb.go | 599 ++++++++++ x/evm/contracts/counter/Counter.go | 2 +- x/evm/contracts/counter/Counter.sol | 2 +- .../contracts/double_counter/DoubleCounter.go | 255 ----- .../double_counter/DoubleCounter.sol | 10 - x/evm/contracts/erc20/ERC20.go | 1007 +++++++++++++++++ x/evm/contracts/erc20/ERC20.sol | 76 ++ .../contracts/erc20_registry/ERC20Registry.go | 203 ++++ .../erc20_registry/ERC20Registry.sol | 29 + x/evm/contracts/factory/Factory.go | 358 ++++++ x/evm/contracts/factory/Factory.sol | 21 + x/evm/contracts/i_erc20/IERC20.go | 430 +++++++ x/evm/contracts/i_erc20/IERC20.sol | 25 + .../i_erc20_registry/IERC20Registry.go | 254 +++++ .../i_erc20_registry/IERC20Registry.sol | 18 + .../i_ibc_async_callback/IIBCAsyncCallback.go | 223 ++++ .../IIBCAsyncCallback.sol | 7 + x/evm/contracts/ownable/Ownable.go | 408 +++++++ x/evm/contracts/ownable/Ownable.sol | 39 + x/evm/keeper/common_test.go | 99 +- x/evm/keeper/context.go | 140 ++- x/evm/keeper/context_test.go | 26 +- x/evm/keeper/erc20.go | 495 ++++++++ x/evm/keeper/erc20_stores.go | 70 ++ x/evm/keeper/erc20_test.go | 293 +++++ x/evm/keeper/genesis.go | 61 +- x/evm/keeper/genesis_test.go | 54 + x/evm/keeper/keeper.go | 67 +- x/evm/keeper/msg_server.go | 56 +- x/evm/keeper/msg_server_test.go | 18 +- x/evm/keeper/precompiles.go | 47 + x/evm/keeper/query_server.go | 50 +- .../erc20_registry/erc20_registry.go | 113 ++ .../erc20_registry/erc20_registry_test.go | 158 +++ x/evm/precompiles/erc20_registry/types.go | 11 + x/evm/types/address.go | 23 + x/evm/types/auth.go | 26 + x/evm/types/auth.pb.go | 326 ++++++ x/evm/types/codec.go | 13 + x/evm/types/denom.go | 45 + x/evm/types/errors.go | 15 +- x/evm/types/events.go | 4 + x/evm/types/expected_keeper.go | 59 + x/evm/types/genesis.go | 5 + x/evm/types/genesis.pb.go | 632 ++++++++++- x/evm/types/keys.go | 10 +- x/evm/types/log.go | 3 +- x/evm/types/query.pb.go | 989 ++++++++++++++-- x/evm/types/query.pb.gw.go | 184 +++ x/evm/types/tx.pb.go | 158 ++- x/evm/types/types.pb.go | 65 +- 91 files changed, 12279 insertions(+), 811 deletions(-) create mode 100644 app/ibc-hooks/README.md create mode 100644 app/ibc-hooks/ack.go create mode 100644 app/ibc-hooks/common_test.go create mode 100644 app/ibc-hooks/hooks.go create mode 100644 app/ibc-hooks/message.go create mode 100644 app/ibc-hooks/receive.go create mode 100644 app/ibc-hooks/receive_test.go create mode 100644 app/ibc-hooks/timeout.go create mode 100644 app/ibc-hooks/util.go create mode 100644 app/ibc-hooks/util_test.go create mode 100644 proto/minievm/bank/v1/tx.proto create mode 100644 proto/minievm/evm/v1/auth.proto create mode 100644 x/bank/autocli.go create mode 100644 x/bank/keeper/common_test.go create mode 100644 x/bank/keeper/custom_msg_server.go create mode 100644 x/bank/keeper/custom_msg_server_test.go create mode 100644 x/bank/keeper/genesis.go create mode 100644 x/bank/keeper/genesis_test.go create mode 100644 x/bank/keeper/grpc_query.go create mode 100644 x/bank/keeper/grpc_query_test.go create mode 100644 x/bank/keeper/keeper.go create mode 100644 x/bank/keeper/keeper_test.go create mode 100644 x/bank/keeper/msg_server.go create mode 100644 x/bank/keeper/msg_server_test.go create mode 100644 x/bank/keeper/send.go create mode 100644 x/bank/keeper/view.go create mode 100644 x/bank/module.go create mode 100644 x/bank/types/codec.go create mode 100644 x/bank/types/tx.pb.go delete mode 100644 x/evm/contracts/double_counter/DoubleCounter.go delete mode 100644 x/evm/contracts/double_counter/DoubleCounter.sol create mode 100644 x/evm/contracts/erc20/ERC20.go create mode 100644 x/evm/contracts/erc20/ERC20.sol create mode 100644 x/evm/contracts/erc20_registry/ERC20Registry.go create mode 100644 x/evm/contracts/erc20_registry/ERC20Registry.sol create mode 100644 x/evm/contracts/factory/Factory.go create mode 100644 x/evm/contracts/factory/Factory.sol create mode 100644 x/evm/contracts/i_erc20/IERC20.go create mode 100644 x/evm/contracts/i_erc20/IERC20.sol create mode 100644 x/evm/contracts/i_erc20_registry/IERC20Registry.go create mode 100644 x/evm/contracts/i_erc20_registry/IERC20Registry.sol create mode 100644 x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.go create mode 100644 x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.sol create mode 100644 x/evm/contracts/ownable/Ownable.go create mode 100644 x/evm/contracts/ownable/Ownable.sol create mode 100644 x/evm/keeper/erc20.go create mode 100644 x/evm/keeper/erc20_stores.go create mode 100644 x/evm/keeper/erc20_test.go create mode 100644 x/evm/keeper/genesis_test.go create mode 100644 x/evm/keeper/precompiles.go create mode 100644 x/evm/precompiles/erc20_registry/erc20_registry.go create mode 100644 x/evm/precompiles/erc20_registry/erc20_registry_test.go create mode 100644 x/evm/precompiles/erc20_registry/types.go create mode 100644 x/evm/types/auth.go create mode 100644 x/evm/types/auth.pb.go create mode 100644 x/evm/types/denom.go diff --git a/app/app.go b/app/app.go index cc4dd70..8ff242e 100644 --- a/app/app.go +++ b/app/app.go @@ -58,8 +58,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/authz" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" - "github.com/cosmos/cosmos-sdk/x/bank" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/consensus" consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" @@ -140,6 +138,8 @@ import ( appkeepers "github.com/initia-labs/minievm/app/keepers" applanes "github.com/initia-labs/minievm/app/lanes" + "github.com/initia-labs/minievm/x/bank" + bankkeeper "github.com/initia-labs/minievm/x/bank/keeper" "github.com/initia-labs/minievm/x/evm" evmconfig "github.com/initia-labs/minievm/x/evm/config" evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" @@ -203,7 +203,7 @@ type MinitiaApp struct { // keepers AccountKeeper *authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper + BankKeeper *bankkeeper.BaseKeeper CapabilityKeeper *capabilitykeeper.Keeper UpgradeKeeper *upgradekeeper.Keeper GroupKeeper *groupkeeper.Keeper @@ -328,6 +328,7 @@ func NewMinitiaApp( // add keepers app.EVMKeeper = &evmkeeper.Keeper{} + erc20Keeper := new(evmkeeper.ERC20Keeper) accountKeeper := authkeeper.NewAccountKeeper( appCodec, @@ -340,14 +341,15 @@ func NewMinitiaApp( ) app.AccountKeeper = &accountKeeper - app.BankKeeper = bankkeeper.NewBaseKeeper( + bankKeeper := bankkeeper.NewBaseKeeper( appCodec, runtime.NewKVStoreService(keys[banktypes.StoreKey]), app.AccountKeeper, + erc20Keeper, app.ModuleAccountAddrs(), authorityAddr, - logger, ) + app.BankKeeper = &bankKeeper communityPoolKeeper := appkeepers.NewCommunityPoolKeeper(app.BankKeeper, authtypes.FeeCollectorName) @@ -621,15 +623,16 @@ func NewMinitiaApp( ////////////////////////////// evmConfig := evmconfig.GetConfig(appOpts) - // The last arguments can contain custom message handlers, and custom query handlers, - // if we want to allow any custom callbacks app.EVMKeeper = evmkeeper.NewKeeper( ac, appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), + accountKeeper, + communityPoolKeeper, authorityAddr, evmConfig, ) + *erc20Keeper = *app.EVMKeeper.ERC20Keeper().(*evmkeeper.ERC20Keeper) // x/auction module keeper initialization @@ -657,7 +660,7 @@ func NewMinitiaApp( app.ModuleManager = module.NewManager( auth.NewAppModule(appCodec, *app.AccountKeeper, nil, nil), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil), + bank.NewAppModule(appCodec, *app.BankKeeper, app.AccountKeeper), opchild.NewAppModule(appCodec, *app.OPChildKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper, false), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, *app.FeeGrantKeeper, app.interfaceRegistry), @@ -723,13 +726,12 @@ func NewMinitiaApp( // so that other modules that want to create or claim capabilities afterwards in InitChain // can do so safely. genesisModuleOrder := []string{ - capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, + capabilitytypes.ModuleName, authtypes.ModuleName, evmtypes.ModuleName, banktypes.ModuleName, opchildtypes.ModuleName, genutiltypes.ModuleName, authz.ModuleName, group.ModuleName, upgradetypes.ModuleName, feegrant.ModuleName, consensusparamtypes.ModuleName, ibcexported.ModuleName, ibctransfertypes.ModuleName, icatypes.ModuleName, icaauthtypes.ModuleName, - ibcfeetypes.ModuleName, auctiontypes.ModuleName, - evmtypes.ModuleName, oracletypes.ModuleName, packetforwardtypes.ModuleName, - icqtypes.ModuleName, fetchpricetypes.ModuleName, + ibcfeetypes.ModuleName, auctiontypes.ModuleName, oracletypes.ModuleName, + packetforwardtypes.ModuleName, icqtypes.ModuleName, fetchpricetypes.ModuleName, } app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) diff --git a/app/ibc-hooks/README.md b/app/ibc-hooks/README.md new file mode 100644 index 0000000..daffc3e --- /dev/null +++ b/app/ibc-hooks/README.md @@ -0,0 +1,164 @@ +# IBC-hooks + +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 + +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. +This is useful for a variety of use cases. +One of primary importance is cross-chain swaps, which is an extremely powerful primitive. + +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 + +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: + +```go +// HookData defines a wrapper for evm execute message +// and async callback. +type HookData struct { + // Message is a evm execute message which will be executed + // at `OnRecvPacket` of receiver chain. + Message evmtypes.MsgCall `json:"message"` + + // AsyncCallback is a callback message which will be executed + // at `OnTimeoutPacket` and `OnAcknowledgementPacket` of + // sender chain. + AsyncCallback *AsyncCallback `json:"async_callback,omitempty"` +} + +// AsyncCallback is data wrapper which is required +// when we implement async callback. +type AsyncCallback struct { + // callback id should be issued form the executor contract + Id uint64 `json:"id"` + ContractAddr string `json:"contract_addr"` +} + +// MsgCall is a message to call an Ethereum contract. +type MsgCall struct { + // Sender is the that actor that signed the messages + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + // ContractAddr is the contract address to be executed. + // It can be cosmos address or hex encoded address. + 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"` +} +``` + +So we detail where we want to get each of these fields from: + +- Sender: We cannot trust the sender of an IBC packet, the counter-party chain has full ability to lie about it. + We cannot risk this sender being confused for a particular user or module address on Initia. + So we replace the sender with an account to represent the sender prefixed by the channel and a evm module prefix. + This is done by setting the sender to `Bech32(Hash(Hash("ibc-evm-hook-intermediary") + channelID/sender))`, where the channelId is the channel id on the local chain. +- ContractAddr: This field should be directly obtained from the ICS-20 packet metadata +- Input: This field should be directly obtained from the ICS-20 packet metadata. + +So our constructed evm call message that we execute will look like: + +```go +msg := MsgCall{ + // Sender is the that actor that signed the messages + Sender: "init1-hash-of-channel-and-sender", + // ContractAddr is the contract address to be executed. + // It can be cosmos address or hex encoded address. + ContractAddr: packet.data.memo["evm"]["message"]["contract_addr"], + // Hex encoded execution input bytes. + Input: packet.data.memo["evm"]["message"]["input"], +} +``` + +### ICS20 packet structure + +So given the details above, we propogate the implied ICS20 packet data structure. +ICS20 is JSON native, so we use JSON for the memo format. + +```json +{ + //... other ibc fields that we don't care about + "data": { + "denom": "denom on counterparty chain (e.g. uatom)", // will be transformed to the local denom (ibc/...) + "amount": "1000", + "sender": "addr on counterparty chain", // will be transformed + "receiver": "ModuleAddr::ModuleName::FunctionName", + "memo": { + "evm": { + // execute message on receive packet + "message": { + "contract_addr": "0x1", + "input": "hex encoded byte string", + }, + // optional field to get async callback (ack and timeout) + "async_callback": { + "id": 1, + "contract_addr": "0x1" + } + } + } + } +} + +``` + +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"` +- `receiver` == "" || `receiver` == "module_address::module_name::function_name" + +We consider an ICS20 packet as directed towards evmhooks iff all of the following hold: + +- `memo` is not blank +- `memo` is valid JSON +- `memo` has at least one key, with name `"evm"` + +If an ICS20 packet is not directed towards evmhooks, evmhooks doesn't do anything. +If an ICS20 packet is directed towards evmhooks, and is formatted incorrectly, then evmhooks returns an error. + +### Execution flow + +Pre evm hooks: + +- Ensure the incoming IBC packet is cryptogaphically valid +- Ensure the incoming IBC packet is not timed out. + +In evm hooks, pre packet execution: + +- Ensure the packet is correctly formatted (as defined above) +- Edit the receiver to be the hardcoded IBC module account + +In evm hooks, post packet execution: + +- Construct evm message as defined before +- Execute evm message +- if evm message has error, return ErrAck +- otherwise continue through middleware + +### Async Callback + +A contract that sends an IBC transfer, may need to listen for the ACK from that packet. +To allow contracts to listen on the ack of specific packets, we provide Ack callbacks. +The contract, which wants to receive ack callback, have to implement two functions. + +- ibc_ack +- ibc_timeout + +```solidity +interface IIBCAsyncCallback { + function ibc_ack(uint64 callback_id, bool success) external; + function ibc_timeout(uint64 callback_id) external; +} +``` + +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. diff --git a/app/ibc-hooks/ack.go b/app/ibc-hooks/ack.go new file mode 100644 index 0000000..d980336 --- /dev/null +++ b/app/ibc-hooks/ack.go @@ -0,0 +1,98 @@ +package evm_hooks + +import ( + "encoding/hex" + + sdk "github.com/cosmos/cosmos-sdk/types" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + + ibchooks "github.com/initia-labs/initia/x/ibc-hooks" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +func (h EVMHooks) onAckIcs20Packet( + ctx sdk.Context, + im ibchooks.IBCMiddleware, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, + data transfertypes.FungibleTokenPacketData, +) error { + if err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer); err != nil { + return err + } + + isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) + if !isEVMRouted || hookData.AsyncCallback == nil { + return nil + } else if err != nil { + return err + } + + callback := hookData.AsyncCallback + if allowed, err := h.checkACL(im, ctx, callback.ContractAddress); err != nil { + return err + } else if !allowed { + return nil + } + + inputBz, err := h.asyncCallbackABI.Pack(functionNameAck, callback.Id, !isAckError(acknowledgement)) + if err != nil { + return err + } + + _, err = h.execMsg(ctx, &evmtypes.MsgCall{ + Sender: data.Sender, + ContractAddr: callback.ContractAddress, + Input: hex.EncodeToString(inputBz), + }) + if err != nil { + return err + } + + return nil +} + +// func (h EVMHooks) onAckIcs721Packet( +// ctx sdk.Context, +// im ibchooks.IBCMiddleware, +// packet channeltypes.Packet, +// acknowledgement []byte, +// relayer sdk.AccAddress, +// data nfttransfertypes.NonFungibleTokenPacketData, +// ) error { +// if err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer); err != nil { +// return err +// } + +// isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) +// if !isEVMRouted || hookData.AsyncCallback == nil { +// return nil +// } else if err != nil { +// return err +// } + +// callback := hookData.AsyncCallback +// if allowed, err := h.checkACL(im, ctx, callback.ContractAddress); err != nil { +// return err +// } else if !allowed { +// return nil +// } + +// inputBz, err := h.asyncCallbackABI.Pack(functionNameAck, callback.Id, !isAckError(acknowledgement)) +// if err != nil { +// return err +// } + +// _, err = h.execMsg(ctx, &evmtypes.MsgCall{ +// Sender: data.Sender, +// ContractAddr: callback.ContractAddress, +// Input: hex.EncodeToString(inputBz), +// }) +// if err != nil { +// return err +// } + +// return nil +// } diff --git a/app/ibc-hooks/common_test.go b/app/ibc-hooks/common_test.go new file mode 100644 index 0000000..c5b970a --- /dev/null +++ b/app/ibc-hooks/common_test.go @@ -0,0 +1,398 @@ +package evm_hooks_test + +import ( + "context" + "encoding/binary" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/ed25519" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/log" + "cosmossdk.io/math" + "cosmossdk.io/store" + "cosmossdk.io/store/metrics" + storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/tx/signing" + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codecaddress "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/std" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/gogoproto/proto" + + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" + + ibchooks "github.com/initia-labs/initia/x/ibc-hooks" + ibchookskeeper "github.com/initia-labs/initia/x/ibc-hooks/keeper" + ibchookstypes "github.com/initia-labs/initia/x/ibc-hooks/types" + + evmhooks "github.com/initia-labs/minievm/app/ibc-hooks" + "github.com/initia-labs/minievm/x/evm" + EVMConfig "github.com/initia-labs/minievm/x/evm/config" + evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var ModuleBasics = module.NewBasicManager( + auth.AppModuleBasic{}, + bank.AppModuleBasic{}, + ibchooks.AppModuleBasic{}, + evm.AppModuleBasic{}, +) + +var ( + initiaSupply = math.NewInt(100_000_000_000) + testDenoms = []string{ + "test1", + "test2", + "test3", + "test4", + "test5", + } +) + +type EncodingConfig struct { + InterfaceRegistry codectypes.InterfaceRegistry + Codec codec.Codec + TxConfig client.TxConfig + Amino *codec.LegacyAmino +} + +func MakeTestCodec(t testing.TB) codec.Codec { + return MakeEncodingConfig(t).Codec +} + +func MakeEncodingConfig(_ testing.TB) EncodingConfig { + interfaceRegistry, _ := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{ + ProtoFiles: proto.HybridResolver, + SigningOptions: signing.Options{ + AddressCodec: codecaddress.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddressCodec: codecaddress.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + }, + }) + appCodec := codec.NewProtoCodec(interfaceRegistry) + legacyAmino := codec.NewLegacyAmino() + txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes) + + std.RegisterInterfaces(interfaceRegistry) + std.RegisterLegacyAminoCodec(legacyAmino) + + ModuleBasics.RegisterLegacyAminoCodec(legacyAmino) + ModuleBasics.RegisterInterfaces(interfaceRegistry) + + return EncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Codec: appCodec, + TxConfig: txConfig, + Amino: legacyAmino, + } +} + +var bondDenom = sdk.DefaultBondDenom + +func initialTotalSupply() sdk.Coins { + faucetBalance := sdk.NewCoins(sdk.NewCoin(bondDenom, initiaSupply)) + for _, testDenom := range testDenoms { + faucetBalance = faucetBalance.Add(sdk.NewCoin(testDenom, initiaSupply)) + } + + return faucetBalance +} + +type TestFaucet struct { + t testing.TB + bankKeeper bankkeeper.Keeper + sender sdk.AccAddress + balance sdk.Coins + minterModuleName string +} + +func NewTestFaucet(t testing.TB, ctx sdk.Context, bankKeeper bankkeeper.Keeper, minterModuleName string, initiaSupply ...sdk.Coin) *TestFaucet { + require.NotEmpty(t, initiaSupply) + r := &TestFaucet{t: t, bankKeeper: bankKeeper, minterModuleName: minterModuleName} + _, _, addr := keyPubAddr() + r.sender = addr + r.Mint(ctx, addr, initiaSupply...) + r.balance = initiaSupply + return r +} + +func (f *TestFaucet) Mint(parentCtx sdk.Context, addr sdk.AccAddress, amounts ...sdk.Coin) { + amounts = sdk.Coins(amounts).Sort() + require.NotEmpty(f.t, amounts) + ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events + err := f.bankKeeper.MintCoins(ctx, f.minterModuleName, amounts) + require.NoError(f.t, err) + err = f.bankKeeper.SendCoinsFromModuleToAccount(ctx, f.minterModuleName, addr, amounts) + require.NoError(f.t, err) + f.balance = f.balance.Add(amounts...) +} + +func (f *TestFaucet) Fund(parentCtx sdk.Context, receiver sdk.AccAddress, amounts ...sdk.Coin) { + require.NotEmpty(f.t, amounts) + // ensure faucet is always filled + if !f.balance.IsAllGTE(amounts) { + f.Mint(parentCtx, f.sender, amounts...) + } + ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events + err := f.bankKeeper.SendCoins(ctx, f.sender, receiver, amounts) + require.NoError(f.t, err) + f.balance = f.balance.Sub(amounts...) +} + +func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress { + _, _, addr := keyPubAddr() + f.Fund(ctx, addr, amounts...) + return addr +} + +type TestKeepers struct { + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + CommunityPoolKeeper *MockCommunityPoolKeeper + IBCHooksKeeper *ibchookskeeper.Keeper + IBCHooksMiddleware ibchooks.IBCMiddleware + EVMKeeper evmkeeper.Keeper + + EncodingConfig EncodingConfig + Faucet *TestFaucet + MultiStore storetypes.CommitMultiStore +} + +// createDefaultTestInput common settings for createTestInput +func createDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) { + return createTestInput(t, false, true) +} + +// createTestInput encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) +func createTestInput(t testing.TB, isCheckTx, initialize bool) (sdk.Context, TestKeepers) { + // Load default move config + return _createTestInput(t, isCheckTx, initialize, dbm.NewMemDB()) +} + +var keyCounter uint64 + +// we need to make this deterministic (same every test run), as encoded address size and thus gas cost, +// depends on the actual bytes (due to ugly CanonicalAddress encoding) +func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { + keyCounter++ + seed := make([]byte, 8) + binary.BigEndian.PutUint64(seed, keyCounter) + + key := ed25519.GenPrivKeyFromSecret(seed) + pub := key.PubKey() + addr := sdk.AccAddress(pub.Address()) + return key, pub, addr +} + +// encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) +func _createTestInput( + t testing.TB, + isCheckTx, initialize bool, + db dbm.DB, +) (sdk.Context, TestKeepers) { + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + distributiontypes.StoreKey, evmtypes.StoreKey, ibchookstypes.StoreKey, + ) + ms := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) + for _, v := range keys { + ms.MountStoreWithDB(v, storetypes.StoreTypeIAVL, db) + } + memKeys := storetypes.NewMemoryStoreKeys() + for _, v := range memKeys { + ms.MountStoreWithDB(v, storetypes.StoreTypeMemory, db) + } + + require.NoError(t, ms.LoadLatestVersion()) + + ctx := sdk.NewContext(ms, tmproto.Header{ + Height: 1, + Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC), + }, isCheckTx, log.NewNopLogger()).WithHeaderHash(make([]byte, 32)) + + encodingConfig := MakeEncodingConfig(t) + appCodec := encodingConfig.Codec + + maccPerms := map[string][]string{ // module account permissions + authtypes.FeeCollectorName: nil, + + // for testing + authtypes.Minter: {authtypes.Minter, authtypes.Burner}, + } + + ac := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + + accountKeeper := authkeeper.NewAccountKeeper( + appCodec, + runtime.NewKVStoreService(keys[authtypes.StoreKey]), // target store + authtypes.ProtoBaseAccount, // prototype + maccPerms, + ac, + sdk.GetConfig().GetBech32AccountAddrPrefix(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + blockedAddrs := make(map[string]bool) + for acc := range maccPerms { + blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true + } + + bankKeeper := bankkeeper.NewBaseKeeper( + appCodec, + runtime.NewKVStoreService(keys[banktypes.StoreKey]), + accountKeeper, + blockedAddrs, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ctx.Logger().With("module", "x/"+banktypes.ModuleName), + ) + require.NoError(t, bankKeeper.SetParams(ctx, banktypes.DefaultParams())) + + ibcHooksKeeper := ibchookskeeper.NewKeeper( + appCodec, + runtime.NewKVStoreService(keys[ibchookstypes.StoreKey]), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ac, + ) + + communityPoolKeeper := &MockCommunityPoolKeeper{} + evmKeeper := evmkeeper.NewKeeper( + ac, + appCodec, + runtime.NewKVStoreService(keys[evmtypes.StoreKey]), + accountKeeper, + communityPoolKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + EVMConfig.DefaultEVMConfig(), + ) + evmParams := evmtypes.DefaultParams() + require.NoError(t, evmKeeper.Params.Set(ctx, evmParams)) + if initialize { + require.NoError(t, evmKeeper.Initialize(ctx)) + } + + faucet := NewTestFaucet(t, ctx, bankKeeper, authtypes.Minter, initialTotalSupply()...) + + // ibc middleware setup + + mockIBCMiddleware := mockIBCMiddleware{} + evmHooks, err := evmhooks.NewEVMHooks(evmKeeper, ac) + require.NoError(t, err) + + middleware := ibchooks.NewICS4Middleware(mockIBCMiddleware, evmHooks) + ibcHookMiddleware := ibchooks.NewIBCMiddleware(mockIBCMiddleware, middleware, ibcHooksKeeper) + + keepers := TestKeepers{ + AccountKeeper: accountKeeper, + CommunityPoolKeeper: communityPoolKeeper, + IBCHooksKeeper: ibcHooksKeeper, + IBCHooksMiddleware: ibcHookMiddleware, + EVMKeeper: *evmKeeper, + BankKeeper: bankKeeper, + EncodingConfig: encodingConfig, + Faucet: faucet, + MultiStore: ms, + } + return ctx, keepers +} + +var _ evmtypes.CommunityPoolKeeper = &MockCommunityPoolKeeper{} + +type MockCommunityPoolKeeper struct { + CommunityPool sdk.Coins +} + +func (k *MockCommunityPoolKeeper) FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error { + k.CommunityPool = k.CommunityPool.Add(amount...) + + return nil +} + +// do nothing ibc middleware +var _ porttypes.IBCModule = mockIBCMiddleware{} +var _ porttypes.ICS4Wrapper = mockIBCMiddleware{} + +type mockIBCMiddleware struct{} + +// GetAppVersion implements types.ICS4Wrapper. +func (m mockIBCMiddleware) GetAppVersion(ctx sdk.Context, portID string, channelID string) (string, bool) { + return "", false +} + +// SendPacket implements types.ICS4Wrapper. +func (m mockIBCMiddleware) SendPacket(ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (sequence uint64, err error) { + return 0, nil +} + +// WriteAcknowledgement implements types.ICS4Wrapper. +func (m mockIBCMiddleware) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error { + return nil +} + +// OnAcknowledgementPacket implements types.IBCModule. +func (m mockIBCMiddleware) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { + return nil +} + +// OnChanCloseConfirm implements types.IBCModule. +func (m mockIBCMiddleware) OnChanCloseConfirm(ctx sdk.Context, portID string, channelID string) error { + return nil +} + +// OnChanCloseInit implements types.IBCModule. +func (m mockIBCMiddleware) OnChanCloseInit(ctx sdk.Context, portID string, channelID string) error { + return nil +} + +// OnChanOpenAck implements types.IBCModule. +func (m mockIBCMiddleware) OnChanOpenAck(ctx sdk.Context, portID string, channelID string, counterpartyChannelID string, counterpartyVersion string) error { + return nil +} + +// OnChanOpenConfirm implements types.IBCModule. +func (m mockIBCMiddleware) OnChanOpenConfirm(ctx sdk.Context, portID string, channelID string) error { + return nil +} + +// OnChanOpenInit implements types.IBCModule. +func (m mockIBCMiddleware) OnChanOpenInit(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) { + return "", nil +} + +// OnChanOpenTry implements types.IBCModule. +func (m mockIBCMiddleware) OnChanOpenTry(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) (version string, err error) { + return "", nil +} + +// OnRecvPacket implements types.IBCModule. +func (m mockIBCMiddleware) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement { + return channeltypes.NewResultAcknowledgement([]byte{byte(1)}) +} + +// OnTimeoutPacket implements types.IBCModule. +func (m mockIBCMiddleware) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + return nil +} diff --git a/app/ibc-hooks/hooks.go b/app/ibc-hooks/hooks.go new file mode 100644 index 0000000..1219312 --- /dev/null +++ b/app/ibc-hooks/hooks.go @@ -0,0 +1,84 @@ +package evm_hooks + +import ( + "cosmossdk.io/core/address" + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" + "github.com/ethereum/go-ethereum/accounts/abi" + + ibchooks "github.com/initia-labs/initia/x/ibc-hooks" + "github.com/initia-labs/minievm/x/evm/contracts/i_ibc_async_callback" + evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" + emvtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var ( + _ ibchooks.OnRecvPacketOverrideHooks = EVMHooks{} + _ ibchooks.OnAcknowledgementPacketOverrideHooks = EVMHooks{} + _ ibchooks.OnTimeoutPacketOverrideHooks = EVMHooks{} +) + +type EVMHooks struct { + evmKeeper *evmkeeper.Keeper + ac address.Codec + asyncCallbackABI *abi.ABI +} + +func NewEVMHooks(evmKeeper *evmkeeper.Keeper, ac address.Codec) (*EVMHooks, error) { + abi, err := i_ibc_async_callback.IIbcAsyncCallbackMetaData.GetAbi() + if err != nil { + return nil, err + } + + return &EVMHooks{ + evmKeeper: evmKeeper, + ac: ac, + asyncCallbackABI: abi, + }, nil +} + +func (h EVMHooks) OnRecvPacketOverride(im ibchooks.IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement { + if isIcs20, ics20Data := isIcs20Packet(packet.GetData()); isIcs20 { + return h.onRecvIcs20Packet(ctx, im, packet, relayer, ics20Data) + } + + // if isIcs721, ics721Data := isIcs721Packet(packet.GetData()); isIcs721 { + // return h.onRecvIcs721Packet(ctx, im, packet, relayer, ics721Data) + // } + + return im.App.OnRecvPacket(ctx, packet, relayer) +} + +func (h EVMHooks) OnAcknowledgementPacketOverride(im ibchooks.IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { + if isIcs20, ics20Data := isIcs20Packet(packet.GetData()); isIcs20 { + return h.onAckIcs20Packet(ctx, im, packet, acknowledgement, relayer, ics20Data) + } + + // if isIcs721, ics721Data := isIcs721Packet(packet.GetData()); isIcs721 { + // return h.onAckIcs721Packet(ctx, im, packet, acknowledgement, relayer, ics721Data) + // } + + return im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) +} + +func (h EVMHooks) OnTimeoutPacketOverride(im ibchooks.IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + if isIcs20, ics20Data := isIcs20Packet(packet.GetData()); isIcs20 { + return h.onTimeoutIcs20Packet(ctx, im, packet, relayer, ics20Data) + } + + // if isIcs721, ics721Data := isIcs721Packet(packet.GetData()); isIcs721 { + // return h.onTimeoutIcs721Packet(ctx, im, packet, relayer, ics721Data) + // } + + return im.App.OnTimeoutPacket(ctx, packet, relayer) +} + +func (h EVMHooks) checkACL(im ibchooks.IBCMiddleware, ctx sdk.Context, addrStr string) (bool, error) { + addr, err := emvtypes.ContractAddressFromString(h.ac, addrStr) + if err != nil { + return false, err + } + + return im.HooksKeeper.GetAllowed(ctx, addr.Bytes()) +} diff --git a/app/ibc-hooks/message.go b/app/ibc-hooks/message.go new file mode 100644 index 0000000..35c738d --- /dev/null +++ b/app/ibc-hooks/message.go @@ -0,0 +1,45 @@ +package evm_hooks + +import ( + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +// A contract that sends an IBC transfer, may need to listen for the ACK from that packet. +// To allow contracts to listen on the ack of specific packets, we provide Ack callbacks. +// +// The contract, which wants to receive ack callback, have to implement two functions +// - ibc_ack +// - ibc_timeout +// +// interface IIBCAsyncCallback { +// function ibc_ack(uint64 callback_id, bool success) external; +// function ibc_timeout(uint64 callback_id) external; +// } +// + +const ( + // The memo key is used to parse ics-20 or ics-712 memo fields. + evmHookMemoKey = "evm" + + functionNameAck = "ibc_ack" + functionNameTimeout = "ibc_timeout" +) + +// AsyncCallback is data wrapper which is required +// when we implement async callback. +type AsyncCallback struct { + // callback id should be issued form the executor contract + Id uint64 `json:"id"` + ContractAddress string `json:"contract_address"` +} + +// HookData defines a wrapper for evm execute message +// and async callback. +type HookData struct { + // Message is a evm execute message which will be executed + // at `OnRecvPacket` of receiver chain. + Message *evmtypes.MsgCall `json:"message,omitempty"` + + // AsyncCallback is a contract address + AsyncCallback *AsyncCallback `json:"async_callback,omitempty"` +} diff --git a/app/ibc-hooks/receive.go b/app/ibc-hooks/receive.go new file mode 100644 index 0000000..dac85ac --- /dev/null +++ b/app/ibc-hooks/receive.go @@ -0,0 +1,135 @@ +package evm_hooks + +import ( + "encoding/json" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" + + ibchooks "github.com/initia-labs/initia/x/ibc-hooks" + + evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +func (h EVMHooks) onRecvIcs20Packet( + ctx sdk.Context, + im ibchooks.IBCMiddleware, + packet channeltypes.Packet, + relayer sdk.AccAddress, + data transfertypes.FungibleTokenPacketData, +) ibcexported.Acknowledgement { + isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) + if !isEVMRouted || hookData.Message == nil { + return im.App.OnRecvPacket(ctx, packet, relayer) + } else if err != nil { + return newEmitErrorAcknowledgement(err) + } + + msg := hookData.Message + if allowed, err := h.checkACL(im, ctx, msg.ContractAddr); err != nil { + return newEmitErrorAcknowledgement(err) + } else if !allowed { + return im.App.OnRecvPacket(ctx, packet, relayer) + } + + // Validate whether the receiver is correctly specified or not. + if err := validateReceiver(msg, data.Receiver); err != nil { + return newEmitErrorAcknowledgement(err) + } + + // Calculate the receiver / contract caller based on the packet's channel and sender + intermediateSender := deriveIntermediateSender(packet.GetDestChannel(), data.GetSender()) + + // The funds sent on this packet need to be transferred to the intermediary account for the sender. + // For this, we override the ICS20 packet's Receiver (essentially hijacking the funds to this new address) + // and execute the underlying OnRecvPacket() call (which should eventually land on the transfer app's + // relay.go and send the funds to the intermediary account. + // + // If that succeeds, we make the contract call + data.Receiver = intermediateSender + bz, err := json.Marshal(data) + if err != nil { + return newEmitErrorAcknowledgement(err) + } + packet.Data = bz + + ack := im.App.OnRecvPacket(ctx, packet, relayer) + if !ack.Success() { + return ack + } + + fmt.Println("SIBONG") + msg.Sender = intermediateSender + _, err = h.execMsg(ctx, msg) + if err != nil { + return newEmitErrorAcknowledgement(err) + } + + return ack +} + +// func (h EVMHooks) onRecvIcs721Packet( +// ctx sdk.Context, +// im ibchooks.IBCMiddleware, +// packet channeltypes.Packet, +// relayer sdk.AccAddress, +// data nfttransfertypes.NonFungibleTokenPacketData, +// ) ibcexported.Acknowledgement { +// isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) +// if !isEVMRouted || hookData.Message == nil { +// return im.App.OnRecvPacket(ctx, packet, relayer) +// } else if err != nil { +// return newEmitErrorAcknowledgement(err) +// } + +// msg := hookData.Message +// if allowed, err := h.checkACL(im, ctx, msg.ContractAddr); err != nil { +// return newEmitErrorAcknowledgement(err) +// } else if !allowed { +// return im.App.OnRecvPacket(ctx, packet, relayer) +// } + +// // Validate whether the receiver is correctly specified or not. +// if err := validateReceiver(msg, data.Receiver); err != nil { +// return newEmitErrorAcknowledgement(err) +// } + +// // Calculate the receiver / contract caller based on the packet's channel and sender +// intermediateSender := deriveIntermediateSender(packet.GetDestChannel(), data.GetSender()) + +// // The funds sent on this packet need to be transferred to the intermediary account for the sender. +// // For this, we override the ICS721 packet's Receiver (essentially hijacking the funds to this new address) +// // and execute the underlying OnRecvPacket() call (which should eventually land on the transfer app's +// // relay.go and send the funds to the intermediary account. +// // +// // If that succeeds, we make the contract call +// data.Receiver = intermediateSender +// bz, err := json.Marshal(data) +// if err != nil { +// return newEmitErrorAcknowledgement(err) +// } +// packet.Data = bz + +// ack := im.App.OnRecvPacket(ctx, packet, relayer) +// if !ack.Success() { +// return ack +// } + +// msg.Sender = intermediateSender +// _, err = h.execMsg(ctx, msg) +// if err != nil { +// return newEmitErrorAcknowledgement(err) +// } + +// return ack +// } + +func (im EVMHooks) execMsg(ctx sdk.Context, msg *evmtypes.MsgCall) (*evmtypes.MsgCallResponse, error) { + evmMsgServer := evmkeeper.NewMsgServerImpl(im.evmKeeper) + return evmMsgServer.Call(ctx, msg) +} diff --git a/app/ibc-hooks/receive_test.go b/app/ibc-hooks/receive_test.go new file mode 100644 index 0000000..68a63f5 --- /dev/null +++ b/app/ibc-hooks/receive_test.go @@ -0,0 +1,103 @@ +package evm_hooks_test + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + + "github.com/initia-labs/minievm/x/evm/contracts/counter" +) + +func Test_onReceiveIcs20Packet_noMemo(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + _, _, addr2 := keyPubAddr() + + // don't have any memo + data := transfertypes.FungibleTokenPacketData{ + Denom: "foo", + Amount: "10000", + Sender: addr.String(), + Receiver: addr2.String(), + Memo: "", + } + + dataBz, err := json.Marshal(&data) + require.NoError(t, err) + + ack := input.IBCHooksMiddleware.OnRecvPacket(ctx, channeltypes.Packet{ + Data: dataBz, + }, addr) + + require.True(t, ack.Success()) +} + +func Test_onReceiveIcs20Packet_memo(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + + codeBz, err := hex.DecodeString(strings.TrimPrefix(counter.CounterBin, "0x")) + require.NoError(t, err) + + _, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, evmAddr, codeBz) + require.NoError(t, err) + + abi, err := counter.CounterMetaData.GetAbi() + require.NoError(t, err) + + inputBz, err := abi.Pack("increase") + require.NoError(t, err) + + // don't have any memo + data := transfertypes.FungibleTokenPacketData{ + Denom: "foo", + Amount: "10000", + Sender: addr.String(), + Receiver: contractAddr.Hex(), + Memo: fmt.Sprintf(`{ + "evm": { + "message": { + "contract_addr": "%s", + "input": "%s" + } + } + }`, contractAddr.Hex(), hex.EncodeToString(inputBz)), + } + + dataBz, err := json.Marshal(&data) + require.NoError(t, err) + + // failed to due to acl + ack := input.IBCHooksMiddleware.OnRecvPacket(ctx, channeltypes.Packet{ + Data: dataBz, + }, addr) + require.False(t, ack.Success()) + + // set acl + require.NoError(t, input.IBCHooksKeeper.SetAllowed(ctx, contractAddr[:], true)) + + // success + ack = input.IBCHooksMiddleware.OnRecvPacket(ctx, channeltypes.Packet{ + Data: dataBz, + }, addr) + require.True(t, ack.Success()) + + queryInputBz, err := abi.Pack("count") + require.NoError(t, err) + + // check the contract state + queryRes, logs, err := input.EVMKeeper.EVMCall(ctx, evmAddr, contractAddr, queryInputBz) + require.NoError(t, err) + require.Equal(t, uint256.NewInt(1).Bytes32(), [32]byte(queryRes)) + require.Empty(t, logs) +} diff --git a/app/ibc-hooks/timeout.go b/app/ibc-hooks/timeout.go new file mode 100644 index 0000000..a106823 --- /dev/null +++ b/app/ibc-hooks/timeout.go @@ -0,0 +1,97 @@ +package evm_hooks + +import ( + "encoding/hex" + + sdk "github.com/cosmos/cosmos-sdk/types" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + + ibchooks "github.com/initia-labs/initia/x/ibc-hooks" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +func (h EVMHooks) onTimeoutIcs20Packet( + ctx sdk.Context, + im ibchooks.IBCMiddleware, + packet channeltypes.Packet, + relayer sdk.AccAddress, + data transfertypes.FungibleTokenPacketData, +) error { + if err := im.App.OnTimeoutPacket(ctx, packet, relayer); err != nil { + return err + } + + isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) + if !isEVMRouted || hookData.AsyncCallback == nil { + return nil + } else if err != nil { + return err + } + + callback := hookData.AsyncCallback + if allowed, err := h.checkACL(im, ctx, callback.ContractAddress); err != nil { + return err + } else if !allowed { + return nil + } + + inputBz, err := h.asyncCallbackABI.Pack(functionNameTimeout, callback.Id) + if err != nil { + return err + } + + _, err = h.execMsg(ctx, &evmtypes.MsgCall{ + Sender: data.Sender, + ContractAddr: callback.ContractAddress, + Input: hex.EncodeToString(inputBz), + }) + if err != nil { + return err + } + + return nil +} + +// func (h EVMHooks) onTimeoutIcs721Packet( +// ctx sdk.Context, +// im ibchooks.IBCMiddleware, +// packet channeltypes.Packet, +// relayer sdk.AccAddress, +// data nfttransfertypes.NonFungibleTokenPacketData, +// ) error { +// if err := im.App.OnTimeoutPacket(ctx, packet, relayer); err != nil { +// return err +// } + +// isEVMRouted, hookData, err := validateAndParseMemo(data.GetMemo()) +// if !isEVMRouted || hookData.AsyncCallback == nil { +// return nil +// } else if err != nil { +// return err +// } + +// callback := hookData.AsyncCallback +// if allowed, err := h.checkACL(im, ctx, callback.ContractAddress); err != nil { +// return err +// } else if !allowed { +// return nil +// } + +// inputBz, err := h.asyncCallbackABI.Pack(functionNameTimeout, callback.Id) +// if err != nil { +// return err +// } + +// _, err = h.execMsg(ctx, &evmtypes.MsgCall{ +// Sender: data.Sender, +// ContractAddr: callback.ContractAddress, +// Input: hex.EncodeToString(inputBz), +// }) +// if err != nil { +// return err +// } + +// return nil +// } diff --git a/app/ibc-hooks/util.go b/app/ibc-hooks/util.go new file mode 100644 index 0000000..8092d93 --- /dev/null +++ b/app/ibc-hooks/util.go @@ -0,0 +1,134 @@ +package evm_hooks + +import ( + "encoding/json" + "fmt" + "strings" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +const senderPrefix = "ibc-evm-hook-intermediary" + +// deriveIntermediateSender compute intermediate sender address +// Bech32(Hash(Hash("ibc-hook-intermediary") + channelID/sender)[12:]) +// +// @dev: use 20bytes of address as intermediate sender address +// +// TODO - make this as module account to check address collision +func deriveIntermediateSender(channel, originalSender string) string { + senderStr := fmt.Sprintf("%s/%s", channel, originalSender) + senderAddr := sdk.AccAddress(address.Hash(senderPrefix, []byte(senderStr))[12:]) + return senderAddr.String() +} + +func isIcs20Packet(packetData []byte) (isIcs20 bool, ics20data transfertypes.FungibleTokenPacketData) { + var data transfertypes.FungibleTokenPacketData + decoder := json.NewDecoder(strings.NewReader(string(packetData))) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&data); err != nil { + return false, data + } + return true, data +} + +// func isIcs721Packet(packetData []byte) (isIcs721 bool, ics721data nfttransfertypes.NonFungibleTokenPacketData) { +// // Use evm port prefix to ack like normal evm chain. +// // +// // initia l1 is handling encoding and decoding depends on port id, +// // so minievm should ack like normal evm chain. +// if data, err := nfttransfertypes.DecodePacketData(packetData, evmPortPrefix); err != nil { +// return false, data +// } else { +// return true, data +// } +// } + +func validateAndParseMemo(memo string) ( + isEVMRouted bool, + hookData HookData, + err error, +) { + isEVMRouted, metadata := jsonStringHasKey(memo, evmHookMemoKey) + if !isEVMRouted { + return + } + + evmHookRaw := metadata[evmHookMemoKey] + + // parse evm raw bytes to execute message + bz, err := json.Marshal(evmHookRaw) + if err != nil { + err = errors.Wrap(channeltypes.ErrInvalidPacket, err.Error()) + return + } + + err = json.Unmarshal(bz, &hookData) + if err != nil { + err = errors.Wrap(channeltypes.ErrInvalidPacket, err.Error()) + return + } + + return +} + +func validateReceiver(msg *evmtypes.MsgCall, receiver string) error { + if receiver != msg.ContractAddr { + return errors.Wrapf(channeltypes.ErrInvalidPacket, "receiver is not properly set") + } + + return nil +} + +// jsonStringHasKey parses the memo as a json object and checks if it contains the key. +func jsonStringHasKey(memo, key string) (found bool, jsonObject map[string]interface{}) { + jsonObject = make(map[string]interface{}) + + // If there is no memo, the packet was either sent with an earlier version of IBC, or the memo was + // intentionally left blank. Nothing to do here. Ignore the packet and pass it down the stack. + if len(memo) == 0 { + return false, jsonObject + } + + // the jsonObject must be a valid JSON object + err := json.Unmarshal([]byte(memo), &jsonObject) + if err != nil { + return false, jsonObject + } + + // If the key doesn't exist, there's nothing to do on this hook. Continue by passing the packet + // down the stack + _, ok := jsonObject[key] + if !ok { + return false, jsonObject + } + + return true, jsonObject +} + +// newEmitErrorAcknowledgement creates a new error acknowledgement after having emitted an event with the +// details of the error. +func newEmitErrorAcknowledgement(err error) channeltypes.Acknowledgement { + return channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: fmt.Sprintf("ibc evm hook error: %s", err.Error()), + }, + } +} + +// isAckError checks an IBC acknowledgement to see if it's an error. +// This is a replacement for ack.Success() which is currently not working on some circumstances +func isAckError(acknowledgement []byte) bool { + var ackErr channeltypes.Acknowledgement_Error + if err := json.Unmarshal(acknowledgement, &ackErr); err == nil && len(ackErr.Error) > 0 { + return true + } + return false +} diff --git a/app/ibc-hooks/util_test.go b/app/ibc-hooks/util_test.go new file mode 100644 index 0000000..84c319b --- /dev/null +++ b/app/ibc-hooks/util_test.go @@ -0,0 +1,106 @@ +package evm_hooks + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + + nfttransfertypes "github.com/initia-labs/initia/x/ibc/nft-transfer/types" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +func Test_isIcs20Packet(t *testing.T) { + transferMsg := transfertypes.NewFungibleTokenPacketData("denom", "1000000", "0x1", "0x2", "memo") + bz, err := json.Marshal(transferMsg) + require.NoError(t, err) + + ok, _transferMsg := isIcs20Packet(bz) + require.True(t, ok) + require.Equal(t, transferMsg, _transferMsg) + + nftTransferMsg := nfttransfertypes.NewNonFungibleTokenPacketData("class_id", "uri", "data", []string{"1", "2", "3"}, []string{"uri1", "uri2", "uri3"}, []string{"data1", "data2", "data3"}, "sender", "receiver", "memo") + bz, err = json.Marshal(nftTransferMsg) + require.NoError(t, err) + + ok, _ = isIcs20Packet(bz) + require.False(t, ok) +} + +// func Test_isIcs721Packet(t *testing.T) { +// nftTransferMsg := nfttransfertypes.NewNonFungibleTokenPacketData("class_id", "uri", "data", []string{"1", "2", "3"}, []string{"uri1", "uri2", "uri3"}, []string{"data1", "data2", "data3"}, "sender", "receiver", "memo") + +// ok, _nftTransferMsg := isIcs721Packet(nftTransferMsg.GetBytes(evmPortPrefix)) +// require.True(t, ok) +// require.Equal(t, nftTransferMsg, _nftTransferMsg) + +// transferMsg := transfertypes.NewFungibleTokenPacketData("denom", "1000000", "0x1", "0x2", "memo") +// ok, _ = isIcs721Packet(transferMsg.GetBytes()) +// require.False(t, ok) +// } + +func Test_validateAndParseMemo_without_callback(t *testing.T) { + memo := `{ + "evm" : { + "message": { + "sender": "init_addr", + "contract_addr": "contract_addr", + "input": "010203040506" + } + } + }` + isEVMRouted, hookData, err := validateAndParseMemo(memo) + require.True(t, isEVMRouted) + require.NoError(t, err) + require.Equal(t, HookData{ + Message: &evmtypes.MsgCall{ + Sender: "init_addr", + ContractAddr: "contract_addr", + Input: "010203040506", + }, + AsyncCallback: nil, + }, hookData) + require.NoError(t, validateReceiver(hookData.Message, "contract_addr")) + + // invalid receiver + require.NoError(t, err) + require.Error(t, validateReceiver(hookData.Message, "invalid_addr")) + + isEVMRouted, _, err = validateAndParseMemo("hihi") + require.False(t, isEVMRouted) + require.NoError(t, err) +} + +func Test_validateAndParseMemo_with_callback(t *testing.T) { + memo := `{ + "evm" : { + "message": { + "sender": "init_addr", + "contract_addr": "contract_addr", + "input": "010203040506" + }, + "async_callback": { + "id": 1, + "contract_address": "0x1" + } + } + }` + isEVMRouted, hookData, err := validateAndParseMemo(memo) + require.True(t, isEVMRouted) + require.NoError(t, err) + require.Equal(t, HookData{ + Message: &evmtypes.MsgCall{ + Sender: "init_addr", + ContractAddr: "contract_addr", + Input: "010203040506", + }, + AsyncCallback: &AsyncCallback{ + Id: 1, + ContractAddress: "0x1", + }, + }, hookData) + require.NoError(t, validateReceiver(hookData.Message, "contract_addr")) +} diff --git a/app/ibc-middleware/util_test.go b/app/ibc-middleware/util_test.go index 77df3d4..25605b0 100644 --- a/app/ibc-middleware/util_test.go +++ b/app/ibc-middleware/util_test.go @@ -23,7 +23,7 @@ func Test_validateAndParseMemo(t *testing.T) { require.Equal(t, evmtypes.MsgCall{ Sender: "init_addr", ContractAddr: "contract_addr", - Input: []byte(""), + Input: "", }, msg) // invalid receiver diff --git a/app/upgrade.go b/app/upgrade.go index 5763855..a0a12af 100644 --- a/app/upgrade.go +++ b/app/upgrade.go @@ -4,7 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" ) -const upgradeName = "0.2.0-beta.3" +// const upgradeName = "0.2.0-beta.3" // RegisterUpgradeHandlers returns upgrade handlers func (app *MinitiaApp) RegisterUpgradeHandlers(cfg module.Configurator) { diff --git a/go.mod b/go.mod index 13634df..25296ac 100644 --- a/go.mod +++ b/go.mod @@ -9,30 +9,31 @@ require ( cosmossdk.io/core v0.11.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.3.1 - cosmossdk.io/math v1.2.0 + cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.0.2 cosmossdk.io/tools/confix v0.1.1 cosmossdk.io/x/feegrant v0.1.0 - cosmossdk.io/x/tx v0.13.0 + cosmossdk.io/x/tx v0.13.1 cosmossdk.io/x/upgrade v0.1.1 github.com/cometbft/cometbft v0.38.5 - github.com/cosmos/cosmos-db v1.0.0 + github.com/cosmos/cosmos-db v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.4 github.com/cosmos/cosmos-sdk v0.50.4 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.11 - github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.0 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.1 github.com/cosmos/ibc-apps/modules/async-icq/v8 v8.0.0 github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.0.0 github.com/ethereum/go-ethereum v1.13.14 github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.3 + github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/hashicorp/go-metrics v0.5.2 github.com/holiman/uint256 v1.2.4 - github.com/initia-labs/OPinit v0.2.0-beta.1 - github.com/initia-labs/initia v0.2.0-beta.7.1 + github.com/initia-labs/OPinit v0.2.2 + github.com/initia-labs/initia v0.2.3 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/skip-mev/block-sdk v0.0.0-20231213233341-deceeb0e993b @@ -40,28 +41,30 @@ require ( github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 - github.com/stretchr/testify v1.8.4 - google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 - google.golang.org/grpc v1.61.0 - google.golang.org/protobuf v1.32.0 + github.com/stretchr/testify v1.9.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - cloud.google.com/go v0.110.10 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/storage v1.36.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect + github.com/IGLOU-EU/go-wildcard v1.0.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/aptos-labs/serde-reflection/serde-generate/runtime/golang v0.0.0-20231213012317-73b6bbf74833 // indirect github.com/aws/aws-sdk-go v1.44.224 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -87,7 +90,7 @@ require ( github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/creachadair/atomicfile v0.3.1 // indirect github.com/creachadair/tomledit v0.0.24 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -101,7 +104,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.1 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -110,6 +113,8 @@ require ( github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -122,7 +127,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect @@ -133,7 +138,6 @@ require ( github.com/hashicorp/go-getter v1.7.3 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-metrics v0.5.2 // indirect github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect @@ -147,9 +151,10 @@ require ( github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/initia-labs/movevm v0.2.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.17.6 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect @@ -200,23 +205,27 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.19.0 // indirect - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.18.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.153.0 // indirect + google.golang.org/api v0.162.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -241,7 +250,7 @@ replace ( // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 - github.com/ethereum/go-ethereum => github.com/initia-labs/go-ethereum v0.0.0-20240306105659-6df78c166d7b + github.com/ethereum/go-ethereum => github.com/initia-labs/go-ethereum v0.0.0-20240326070025-3f6a7e5cd315 // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 diff --git a/go.sum b/go.sum index 4660841..0e41841 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= -cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -68,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -109,8 +109,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= @@ -171,8 +171,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= -cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -198,8 +198,8 @@ cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= -cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= -cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= +cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/simapp v0.0.0-20231211060251-d8fb76d4c267 h1:fLJ+ng4SiuEK7NhKPIAn7QlWNGPpFCzfdtEODUXDvEs= cosmossdk.io/simapp v0.0.0-20231211060251-d8fb76d4c267/go.mod h1:ril3K+x7sdvOTVZsBv0PGDePO54m64HLDq1AmVEREl8= cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= @@ -214,8 +214,8 @@ cosmossdk.io/x/feegrant v0.1.0 h1:c7s3oAq/8/UO0EiN1H5BIjwVntujVTkYs35YPvvrdQk= cosmossdk.io/x/feegrant v0.1.0/go.mod h1:4r+FsViJRpcZif/yhTn+E0E6OFfg4n0Lx+6cCtnZElU= cosmossdk.io/x/nft v0.1.0 h1:VhcsFiEK33ODN27kxKLa0r/CeFd8laBfbDBwYqCyYCM= cosmossdk.io/x/nft v0.1.0/go.mod h1:ec4j4QAO4mJZ+45jeYRnW7awLHby1JZANqe1hNZ4S3g= -cosmossdk.io/x/tx v0.13.0 h1:8lzyOh3zONPpZv2uTcUmsv0WTXy6T1/aCVDCqShmpzU= -cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/tx v0.13.1 h1:Mg+EMp67Pz+NukbJqYxuo8uRp7N/a9uR+oVS9pONtj8= +cosmossdk.io/x/tx v0.13.1/go.mod h1:CBCU6fsRVz23QGFIQBb1DNX2DztJCf3jWyEkHY2nJQ0= cosmossdk.io/x/upgrade v0.1.1 h1:aoPe2gNvH+Gwt/Pgq3dOxxQVU3j5P6Xf+DaUJTDZATc= cosmossdk.io/x/upgrade v0.1.1/go.mod h1:MNLptLPcIFK9CWt7Ra//8WUZAxweyRDNcbs5nkOcQy0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -337,6 +337,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -369,8 +371,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0E= -github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= +github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= +github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= @@ -380,8 +382,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.0 h1:PqaYuNJDpeqisP3Td5djrvFhuVMnOIWFJeqMJuZPRas= -github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.0/go.mod h1:82hPO/tRawbuFad2gPwChvpZ0JEIoNi91LwVneAYCeM= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.1 h1:BHn+JWZILxkUT9IrlP1ctUfo9ENGi+EmiZ9om1XSHIw= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.1/go.mod h1:82hPO/tRawbuFad2gPwChvpZ0JEIoNi91LwVneAYCeM= github.com/cosmos/ibc-apps/modules/async-icq/v8 v8.0.1-0.20240124225747-f055ce5b405c h1:44QAwcoTqB1jT6p7IogVKZwdKVZykX2fg+iU0Q/LTZ0= github.com/cosmos/ibc-apps/modules/async-icq/v8 v8.0.1-0.20240124225747-f055ce5b405c/go.mod h1:D3Q380FpWRFtmUQWLosPxachi6w24Og2t5u/Tww5wtY= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= @@ -401,8 +403,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0q github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= @@ -458,8 +460,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -509,6 +513,11 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -580,8 +589,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -642,8 +651,8 @@ github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -759,20 +768,20 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/initia-labs/OPinit v0.2.0-beta.1 h1:98LhxGZ3ZOcqziSGJgcasq6Wh4tp1KqHkM1CwsGKyQ0= -github.com/initia-labs/OPinit v0.2.0-beta.1/go.mod h1:1dn1iseG1S4wfXUtnb4mUkraJdL9/lWBQPpI+HbVzL0= +github.com/initia-labs/OPinit v0.2.2 h1:lcBQCQcn7zgkpQaKqIfNLaj15Dy6qSDYv62/XJ1iISE= +github.com/initia-labs/OPinit v0.2.2/go.mod h1:1dn1iseG1S4wfXUtnb4mUkraJdL9/lWBQPpI+HbVzL0= github.com/initia-labs/cometbft v0.0.0-20240104081544-34081fc84daf h1:7k3u0huB7OpiDfQKnfcwKUvByl7HyYs3itgROO/YpFg= github.com/initia-labs/cometbft v0.0.0-20240104081544-34081fc84daf/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= github.com/initia-labs/cosmos-sdk v0.0.0-20240228122102-ee5ec2e05aea h1:MMBuEk0sxBEVPEfIA0YieIsRc0cqngflS9Q75tiewe4= github.com/initia-labs/cosmos-sdk v0.0.0-20240228122102-ee5ec2e05aea/go.mod h1:UbShFs6P8Ly29xxJvkNGaNaL/UGj5a686NRtb1Cqra0= -github.com/initia-labs/go-ethereum v0.0.0-20240306105659-6df78c166d7b h1:GNPplPfJ3W8F2Ih1vURD2U08EFxQthDTTPdjhamfS4Q= -github.com/initia-labs/go-ethereum v0.0.0-20240306105659-6df78c166d7b/go.mod h1:GgM6g0npk4xWoMJeCe3+kshx9UuzAwTCcm6v5FgC73w= +github.com/initia-labs/go-ethereum v0.0.0-20240326070025-3f6a7e5cd315 h1:Ks+iqkMEOIIdxGk+4/iqER6hUXKFPvOAtdvRLO7JueU= +github.com/initia-labs/go-ethereum v0.0.0-20240326070025-3f6a7e5cd315/go.mod h1:x2gtBG0WHLgY08FE97lfhjtpcR5vcSAZbi34JnrsBbQ= github.com/initia-labs/iavl v0.0.0-20240208034922-5d81c449d4c0 h1:GQ7/UD5mB6q104roqZK5jxb6ff9sBk0/uwFxgERQIaU= github.com/initia-labs/iavl v0.0.0-20240208034922-5d81c449d4c0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= -github.com/initia-labs/initia v0.2.0-beta.7.1 h1:m72+y/htXXYuV6Wg0IROQtC/ZZyF0Y1BD3DmeWmLhSQ= -github.com/initia-labs/initia v0.2.0-beta.7.1/go.mod h1:sCqG5B+KaauSRp7o9DceNtTcGayyvqSEz30+HuYmBs0= -github.com/initia-labs/initiavm v0.2.0-beta.2.1 h1:L6UHFS5LB/somGfgMO0N2tpkas0v+lTBIMkDvZw+S1M= -github.com/initia-labs/initiavm v0.2.0-beta.2.1/go.mod h1:KTdC3W2wgeOiL0YYIu6MEvK4j8envSpLjH14sMKMD6k= +github.com/initia-labs/initia v0.2.3 h1:btg3UoX6oy7LOcsy03rZaYmxDk5RvOyBY+hQ4EtuxUg= +github.com/initia-labs/initia v0.2.3/go.mod h1:xLkPASIv+6EuE7BHCxB3ag2K9+rUwJ/6AC5fkYmSejw= +github.com/initia-labs/movevm v0.2.2 h1:T0FwprEEDWhNfPREthNDvRr+IGg9N7eQg+zXvT8V/U4= +github.com/initia-labs/movevm v0.2.2/go.mod h1:1EyJ06+Hn43MfaXZ+30a2gmhS5zjqiFF8oSF5CHai28= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= @@ -804,8 +813,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= @@ -900,8 +909,6 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/novifinancial/serde-reflection/serde-generate/runtime/golang v0.0.0-20220519162058-e5cd3c3b3f3a h1:oMG8C4E7DFkat7WQicw4JNa/dYUaqO7RvLPbkFdADIA= -github.com/novifinancial/serde-reflection/serde-generate/runtime/golang v0.0.0-20220519162058-e5cd3c3b3f3a/go.mod h1:NrRYJCFtaewjIRr4B9V2AyWsAEMW0Zqdjs8Bm+bACbM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -1085,8 +1092,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1099,8 +1106,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= @@ -1161,6 +1169,18 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1196,8 +1216,8 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1209,8 +1229,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1450,16 +1470,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1603,8 +1623,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= -google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1722,12 +1742,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= -google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1769,8 +1789,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1788,8 +1808,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/proto/buf.lock b/proto/buf.lock index f07996b..1815c6a 100644 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -9,35 +9,25 @@ deps: - remote: buf.build owner: cosmos repository: cosmos-sdk - commit: 05419252bcc241ea8023acf1ed4cadc5 - digest: shake256:1e54a48c19a8b59d35e0a7efa76402939f515f2d8005df099856f24c37c20a52800308f025abb8cffcd014d437b49707388aaca4865d9d063d8f25d5d4eb77d5 + commit: 5a6ab7bc14314acaa912d5e53aef1c2f + digest: shake256:02c00c73493720055f9b57553a35b5550023a3c1914123b247956288a78fb913aff70e66552777ae14d759467e119079d484af081264a5dd607a94d9fbc8116b - remote: buf.build owner: cosmos repository: gogo-proto - commit: 88ef6483f90f478fb938c37dde52ece3 - digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba + commit: 5e5b9fdd01804356895f8f79a6f1ddc1 + digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 - remote: buf.build owner: cosmos repository: ibc - commit: b32ecf3ebbcb45f3b727ae95d9ea317d - digest: shake256:0010f681e8a1b37d5331dbd93fa07486572caaea564137fa040438e81c99b7f516adcef4991752972331771d95e757b794c4f28ffcd0f6c832f0793f8089f30d + commit: cc1d31ac98a0477580379346dab8e87b + digest: shake256:eb94a4dcb8476c0061df09486222f4c1a909334106fc99fdbb9c429e2148f9570bc767da8257b222ca20d9b578b5c80c87953613e746a6b8d7ceb85c3fc03038 - remote: buf.build owner: cosmos repository: ics23 - commit: a9ee7c290ef34ee69d3f141b9b44dcee - digest: shake256:255dbee3e92a370723bf4d72b34868b18e7570543f30f79c0c8c10a5a332d230175e0c29cb7ebcb8020706312e3cd37c23974df0bacfb60a4afb968fee4c1afc + commit: 55085f7c710a45f58fa09947208eb70b + digest: shake256:9bf0bc495b5a11c88d163d39ef521bc4b00bc1374a05758c91d82821bdc61f09e8c2c51dda8452529bf80137f34d852561eacbe9550a59015d51cecb0dacb628 - remote: buf.build owner: googleapis repository: googleapis - commit: 7e6f6e774e29406da95bd61cdcdbc8bc - digest: shake256:fe43dd2265ea0c07d76bd925eeba612667cf4c948d2ce53d6e367e1b4b3cb5fa69a51e6acb1a6a50d32f894f054a35e6c0406f6808a483f2752e10c866ffbf73 - - remote: buf.build - owner: protocolbuffers - repository: wellknowntypes - commit: 657250e6a39648cbb169d079a60bd9ba - digest: shake256:00de25001b8dd2e29d85fc4bcc3ede7aed886d76d67f5e0f7a9b320b90f871d3eb73507d50818d823a0512f3f8db77a11c043685528403e31ff3fef18323a9fb - - remote: buf.build - owner: tendermint - repository: tendermint - commit: 33ed361a90514289beabf3189e1d7665 - digest: shake256:038267e06294714fd883610626554b04a127b576b4e253befb4206cb72d5d3c1eeccacd4b9ec8e3fb891f7c14e1cb0f770c077d2989638995b0a61c85afedb1d + commit: cc916c31859748a68fd229a3c8d7a2e8 + digest: shake256:469b049d0eb04203d5272062636c078decefc96fec69739159c25d85349c50c34c7706918a8b216c5c27f76939df48452148cff8c5c3ae77fa6ba5c25c1b8bf8 diff --git a/proto/buf.yaml b/proto/buf.yaml index 668cdac..c1d8713 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -2,12 +2,12 @@ version: v1 name: buf.build/initia-labs/minievm deps: - - buf.build/cosmos/cosmos-sdk - - buf.build/cosmos/cosmos-proto - - buf.build/cosmos/gogo-proto - - buf.build/googleapis/googleapis - - buf.build/cosmos/ics23 - - buf.build/cosmos/ibc + - buf.build/cosmos/cosmos-sdk:v0.50.0 + - buf.build/cosmos/cosmos-proto:1935555c206d4afb9e94615dfd0fad31 + - buf.build/cosmos/gogo-proto:5e5b9fdd01804356895f8f79a6f1ddc1 + - buf.build/googleapis/googleapis:cc916c31859748a68fd229a3c8d7a2e8 + - buf.build/cosmos/ics23:b1abd8678aab07165efd453c96796a179eb3131f + - buf.build/cosmos/ibc:cc1d31ac98a0477580379346dab8e87b breaking: use: diff --git a/proto/minievm/bank/v1/tx.proto b/proto/minievm/bank/v1/tx.proto new file mode 100644 index 0000000..9f97a55 --- /dev/null +++ b/proto/minievm/bank/v1/tx.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; +package minievm.bank.v1; + +option go_package = "github.com/initia-labs/minievm/x/bank/types"; +option (gogoproto.equal_all) = false; + +import "amino/amino.proto"; +import "cosmos/bank/v1beta1/bank.proto"; +import "cosmos/msg/v1/msg.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; + +// Msg defines the bank Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // SetDenomMetadata defines a governance operation for updating the x/bank + // denom metadata. The authority is defined in the keeper. + rpc SetDenomMetadata(MsgSetDenomMetadata) returns (MsgSetDenomMetadataResponse); +} + +// MsgSetDenomMetadata is the Msg/UpdateParams request type. +message MsgSetDenomMetadata { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "bank/MsgSetDenomMetadata"; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // metadata defines the x/bank denom metadata to update. + cosmos.bank.v1beta1.Metadata metadata = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; +} + +// MsgSetDenomMetadataResponse defines the response structure for executing a +// MsgSetDenomMetadata message. +message MsgSetDenomMetadataResponse {} diff --git a/proto/minievm/evm/v1/auth.proto b/proto/minievm/evm/v1/auth.proto new file mode 100644 index 0000000..ad45ee0 --- /dev/null +++ b/proto/minievm/evm/v1/auth.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package minievm.evm.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/auth/v1beta1/auth.proto"; + +option go_package = "github.com/initia-labs/minievm/x/evm/types"; + +// ContractAccount defines an account for contract account. +message ContractAccount { + option (amino.name) = "evm/ContractAccount"; + option (gogoproto.goproto_getters) = false; + + cosmos.auth.v1beta1.BaseAccount base_account = 1 [(gogoproto.embed) = true]; +} + diff --git a/proto/minievm/evm/v1/genesis.proto b/proto/minievm/evm/v1/genesis.proto index bd000d9..4564699 100644 --- a/proto/minievm/evm/v1/genesis.proto +++ b/proto/minievm/evm/v1/genesis.proto @@ -16,12 +16,29 @@ message GenesisState { // vm kv store repeated GenesisKeyValue key_values = 3 [(gogoproto.moretags) = "yaml:\"key_values\"", (gogoproto.nullable) = false]; + + // erc20 stores + repeated GenesisERC20Stores erc20_stores = 4 + [(gogoproto.moretags) = "yaml:\"erc20_stores\"", (gogoproto.nullable) = false]; + + repeated GenesisDenomAddress denom_addresses = 5 + [(gogoproto.moretags) = "yaml:\"denom_addresses\"", (gogoproto.nullable) = false]; } -// GenesisDenom defines a evm denom that is defined within genesis -// state. The structure contains DenomAuthorityMetadata which defines the -// denom's admin. +// GenesisKeyValue defines store KV values. message GenesisKeyValue { bytes key = 1; bytes value = 2; +} + +// GenesisERC20Stores defines erc20 contract addresses of an account. +message GenesisERC20Stores { + bytes address = 1; + repeated bytes stores = 2; +} + +// GenesisDenomAddress defines erc20 contract address of denom. +message GenesisDenomAddress { + string denom = 1; + bytes contract_address = 2; } \ No newline at end of file diff --git a/proto/minievm/evm/v1/query.proto b/proto/minievm/evm/v1/query.proto index f7e30b8..ecba905 100644 --- a/proto/minievm/evm/v1/query.proto +++ b/proto/minievm/evm/v1/query.proto @@ -22,6 +22,14 @@ service Query { option (google.api.http).get = "/minievm/evm/v1/states/{contract_addr}/{key}"; } + rpc ContractAddrByDenom(QueryContractAddrByDenomRequest) returns (QueryContractAddrByDenomResponse) { + option (google.api.http).get = "/minievm/evm/v1/contracts/by_denom"; + } + + rpc Denom(QueryDenomRequest) returns (QueryDenomResponse) { + option (google.api.http).get = "/minievm/evm/v1/denoms/{contract_addr}"; + } + // Call execute entry function and return the function result rpc Call(QueryCallRequest) returns (QueryCallResponse) { option (google.api.http) = { @@ -39,7 +47,7 @@ service Query { // QueryCodeRequest is the request type for the Query/Code RPC // method message QueryCodeRequest { - // contract address to query + // hex encoded contract address to query string contract_addr = 1; } @@ -53,7 +61,7 @@ message QueryCodeResponse { // QueryStateRequest is the request type for the Query/State RPC // method message QueryStateRequest { - // contract address to query + // It can be cosmos address or hex encoded address (0x prefixed). string contract_addr = 1; // hex encoded hash string string key = 2; @@ -72,20 +80,49 @@ message QueryStateResponse { message QueryCallRequest { // sender address string sender = 1; - // contract address to call + // It can be cosmos address or hex encoded address (0x prefixed). string contract_addr = 2; - // call input bytes - bytes input = 3; + // hex encoded call input + string input = 3; } // QueryCallResponse is the response type for the Query/Call RPC // method message QueryCallResponse { - bytes response = 1; + // hex encoded response bytes. + string response = 1; uint64 used_gas = 2; repeated Log logs = 3 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; } +// QueryContractAddrByDenomRequest is the request type for the Query/ContractAddrByDenom RPC +// method +message QueryContractAddrByDenomRequest { + string denom = 1; +} + +// QueryContractAddrByDenomResponse is the response type for the Query/ContractAddrByDenom RPC +// method +message QueryContractAddrByDenomResponse { + option (gogoproto.equal) = true; + // 0x prefixed hex address + string address = 1; +} + +// QueryDenomRequest is the request type for the Query/Denom RPC +// method +message QueryDenomRequest { + // It can be cosmos address or hex encoded address (0x prefixed). + string contract_addr = 1; +} + +// QueryDenomResponse is the response type for the Query/Denom RPC +// method +message QueryDenomResponse { + option (gogoproto.equal) = true; + string denom = 1; +} + // QueryParamsRequest is the request type for the Query/Params RPC method. message QueryParamsRequest {} diff --git a/proto/minievm/evm/v1/tx.proto b/proto/minievm/evm/v1/tx.proto index 1c788c3..6012f8c 100644 --- a/proto/minievm/evm/v1/tx.proto +++ b/proto/minievm/evm/v1/tx.proto @@ -31,15 +31,15 @@ message MsgCreate { // Sender is the that actor that signed the messages string sender = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; - // Code is raw contract bytes code. - bytes code = 2; + // Code is hex encoded raw contract bytes code. + string code = 2; } // MsgCreateResponse defines the Msg/Create response type. message MsgCreateResponse { - bytes result = 1; + string result = 1; - // hex encoded contract address + // hex encoded address (0x prefixed) string contract_addr = 2; } @@ -52,16 +52,16 @@ message MsgCall { string sender = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // ContractAddr is the contract address to be executed. - // It can be cosmos address or hex encoded address. + // It can be cosmos address or hex encoded address (0x prefixed). string contract_addr = 2; - // Execution input bytes. - bytes input = 3; + // Hex encoded execution input bytes. + string input = 3; } // MsgCallResponse defines the Msg/Call response type. message MsgCallResponse { - bytes result = 1; + string result = 1; repeated Log logs = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; } diff --git a/proto/minievm/evm/v1/types.proto b/proto/minievm/evm/v1/types.proto index 267c686..2cdd077 100644 --- a/proto/minievm/evm/v1/types.proto +++ b/proto/minievm/evm/v1/types.proto @@ -23,7 +23,7 @@ message Params { [(gogoproto.moretags) = "yaml:\"allowed_publishers\"", (amino.dont_omitempty) = true]; } -// Log represents a contract log event. These events are generated by +// Log represents a contract log event. These events are generated by // the LOG opcode and stored/indexed by the node. message Log { // address of the contract that generated the event @@ -31,5 +31,5 @@ message Log { // list of topics provided by the contract. repeated string topics = 2; // supplied by the contract, usually ABI-encoded - bytes data = 3; + string data = 3; } \ No newline at end of file diff --git a/scripts/contractsgen.sh b/scripts/contractsgen.sh index c504b4b..8e1a636 100644 --- a/scripts/contractsgen.sh +++ b/scripts/contractsgen.sh @@ -3,15 +3,19 @@ CONTRACTS_DIR=x/evm/contracts for CONTRACT_HOME in $CONTRACTS_DIR/*; do if [ -d "$CONTRACT_HOME" ]; then PKG_NAME=$(basename $CONTRACT_HOME) - CONTRACT_PATH=$(find $CONTRACT_HOME -type f -name "*.sol") - CONTRACT_NAME=$(basename $CONTRACT_PATH .sol) - echo $CONTRACT_HOME $PKG_NAME $CONTRACT_PATH $CONTRACT_NAME + for CONTRACT_PATH in $CONTRACT_HOME/*; do + if [ "${CONTRACT_PATH: -4}" == ".sol" ]; then + echo $CONTRACT_PATH + CONTRACT_NAME=$(basename $CONTRACT_PATH .sol) + echo $CONTRACT_HOME $PKG_NAME $CONTRACT_PATH $CONTRACT_NAME - solc $CONTRACT_PATH --bin --abi -o $BUILD_DIR --overwrite - abigen --pkg $PKG_NAME \ - --bin=$BUILD_DIR/$CONTRACT_NAME.bin \ - --abi=$BUILD_DIR/$CONTRACT_NAME.abi \ - --out=$CONTRACT_HOME/$CONTRACT_NAME.go + solc $CONTRACT_PATH --bin --abi -o $BUILD_DIR --overwrite + abigen --pkg $PKG_NAME \ + --bin=$BUILD_DIR/$CONTRACT_NAME.bin \ + --abi=$BUILD_DIR/$CONTRACT_NAME.abi \ + --out=$CONTRACT_HOME/$CONTRACT_NAME.go + fi + done fi #solc $(ls $${file}/*.sol) --bin --abi -o build diff --git a/x/bank/autocli.go b/x/bank/autocli.go new file mode 100644 index 0000000..4224dba --- /dev/null +++ b/x/bank/autocli.go @@ -0,0 +1,118 @@ +package bank + +import ( + "strings" + + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" +) + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Balance", + Use: "balance [address] [denom]", + Short: "Query an account balance by address and denom", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}, {ProtoField: "denom"}}, + }, + { + RpcMethod: "AllBalances", + Use: "balances [address]", + Short: "Query for account balances by address", + Long: "Query the total balance of an account or of a specific denomination.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}}, + }, + { + RpcMethod: "SpendableBalances", + Use: "spendable-balances [address]", + Short: "Query for account spendable balances by address", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}}, + }, + { + RpcMethod: "SpendableBalanceByDenom", + Use: "spendable-balance [address] [denom]", + Short: "Query the spendable balance of a single denom for a single account.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}, {ProtoField: "denom"}}, + }, + { + RpcMethod: "TotalSupply", + Use: "total-supply", + Alias: []string{"total"}, + Short: "Query the total supply of coins of the chain", + Long: "Query total supply of coins that are held by accounts in the chain. To query for the total supply of a specific coin denomination use --denom flag.", + }, + { + RpcMethod: "SupplyOf", + Use: "total-supply-of [denom]", + Short: "Query the supply of a single coin denom", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}}, + }, + { + RpcMethod: "Params", + Use: "params", + Short: "Query the current bank parameters", + }, + { + RpcMethod: "DenomMetadata", + Use: "denom-metadata [denom]", + Short: "Query the client metadata of a given coin denomination", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}}, + }, + { + RpcMethod: "DenomsMetadata", + Use: "denoms-metadata", + Short: "Query the client metadata for all registered coin denominations", + }, + { + RpcMethod: "DenomOwners", + Use: "denom-owners [denom]", + Short: "Query for all account addresses that own a particular token denomination.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}}, + }, + { + RpcMethod: "SendEnabled", + Use: "send-enabled [denom1 ...]", + Short: "Query for send enabled entries", + Long: strings.TrimSpace(`Query for send enabled entries that have been specifically set. + +To look up one or more specific denoms, supply them as arguments to this command. +To look up all denoms, do not provide any arguments.`, + ), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denoms"}}, + }, + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + EnhanceCustomCommand: false, // use custom commands only until v0.51 + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Send funds from one account to another.", + Long: `Send funds from one account to another. +Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. +When using '--dry-run' a key name cannot be used, only a bech32 address. +Note: multiple coins can be send by space separated.`, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount", Varargs: true}}, + }, + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + { + RpcMethod: "SetSendEnabled", + Skip: true, // skipped because authority gated + }, + { + RpcMethod: "Burn", + Skip: true, // skipped because available from v0.51 + }, + }, + }, + } +} diff --git a/x/bank/keeper/common_test.go b/x/bank/keeper/common_test.go new file mode 100644 index 0000000..a00b516 --- /dev/null +++ b/x/bank/keeper/common_test.go @@ -0,0 +1,319 @@ +package keeper_test + +import ( + "context" + "encoding/binary" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/ed25519" + "github.com/cometbft/cometbft/crypto/secp256k1" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/log" + "cosmossdk.io/math" + "cosmossdk.io/store" + "cosmossdk.io/store/metrics" + storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/tx/signing" + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codecaddress "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/std" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/gogoproto/proto" + + "github.com/initia-labs/minievm/x/bank" + custombankkeeper "github.com/initia-labs/minievm/x/bank/keeper" + "github.com/initia-labs/minievm/x/evm" + EVMConfig "github.com/initia-labs/minievm/x/evm/config" + evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var ModuleBasics = module.NewBasicManager( + auth.AppModuleBasic{}, + bank.AppModuleBasic{}, + evm.AppModuleBasic{}, +) + +var ( + pubKeys = []crypto.PubKey{ + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + secp256k1.GenPrivKey().PubKey(), + } + + addrs = []sdk.AccAddress{ + sdk.AccAddress(pubKeys[0].Address()), + sdk.AccAddress(pubKeys[1].Address()), + sdk.AccAddress(pubKeys[2].Address()), + sdk.AccAddress(pubKeys[3].Address()), + sdk.AccAddress(pubKeys[4].Address()), + } + + initiaSupply = math.NewInt(100_000_000_000) + testDenoms = []string{ + "test1", + "test2", + "test3", + "test4", + "test5", + } +) + +type EncodingConfig struct { + InterfaceRegistry codectypes.InterfaceRegistry + Codec codec.Codec + TxConfig client.TxConfig + Amino *codec.LegacyAmino +} + +func MakeTestCodec(t testing.TB) codec.Codec { + return MakeEncodingConfig(t).Codec +} + +func MakeEncodingConfig(_ testing.TB) EncodingConfig { + interfaceRegistry, _ := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{ + ProtoFiles: proto.HybridResolver, + SigningOptions: signing.Options{ + AddressCodec: codecaddress.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddressCodec: codecaddress.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + }, + }) + appCodec := codec.NewProtoCodec(interfaceRegistry) + legacyAmino := codec.NewLegacyAmino() + txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes) + + std.RegisterInterfaces(interfaceRegistry) + std.RegisterLegacyAminoCodec(legacyAmino) + + ModuleBasics.RegisterLegacyAminoCodec(legacyAmino) + ModuleBasics.RegisterInterfaces(interfaceRegistry) + + return EncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Codec: appCodec, + TxConfig: txConfig, + Amino: legacyAmino, + } +} + +var bondDenom = sdk.DefaultBondDenom + +func initialTotalSupply() sdk.Coins { + faucetBalance := sdk.NewCoins(sdk.NewCoin(bondDenom, initiaSupply)) + for _, testDenom := range testDenoms { + faucetBalance = faucetBalance.Add(sdk.NewCoin(testDenom, initiaSupply)) + } + + return faucetBalance +} + +type TestFaucet struct { + t testing.TB + bankKeeper bankkeeper.Keeper + sender sdk.AccAddress + balance sdk.Coins + minterModuleName string +} + +func NewTestFaucet(t testing.TB, ctx sdk.Context, bankKeeper bankkeeper.Keeper, minterModuleName string, initiaSupply ...sdk.Coin) *TestFaucet { + require.NotEmpty(t, initiaSupply) + r := &TestFaucet{t: t, bankKeeper: bankKeeper, minterModuleName: minterModuleName} + _, _, addr := keyPubAddr() + r.sender = addr + r.Mint(ctx, addr, initiaSupply...) + r.balance = initiaSupply + return r +} + +func (f *TestFaucet) Mint(parentCtx sdk.Context, addr sdk.AccAddress, amounts ...sdk.Coin) { + amounts = sdk.Coins(amounts).Sort() + require.NotEmpty(f.t, amounts) + ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events + err := f.bankKeeper.MintCoins(ctx, f.minterModuleName, amounts) + require.NoError(f.t, err) + err = f.bankKeeper.SendCoinsFromModuleToAccount(ctx, f.minterModuleName, addr, amounts) + require.NoError(f.t, err) + f.balance = f.balance.Add(amounts...) +} + +func (f *TestFaucet) Fund(parentCtx sdk.Context, receiver sdk.AccAddress, amounts ...sdk.Coin) { + require.NotEmpty(f.t, amounts) + // ensure faucet is always filled + if !f.balance.IsAllGTE(amounts) { + f.Mint(parentCtx, f.sender, amounts...) + } + ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events + err := f.bankKeeper.SendCoins(ctx, f.sender, receiver, amounts) + require.NoError(f.t, err) + f.balance = f.balance.Sub(amounts...) +} + +func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress { + _, _, addr := keyPubAddr() + f.Fund(ctx, addr, amounts...) + return addr +} + +type TestKeepers struct { + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + CommunityPoolKeeper *MockCommunityPoolKeeper + EVMKeeper evmkeeper.Keeper + EncodingConfig EncodingConfig + Faucet *TestFaucet + MultiStore storetypes.CommitMultiStore +} + +// createDefaultTestInput common settings for createTestInput +func createDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) { + return createTestInput(t, false) +} + +// createTestInput encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) +func createTestInput(t testing.TB, isCheckTx bool) (sdk.Context, TestKeepers) { + // Load default move config + return _createTestInput(t, isCheckTx, dbm.NewMemDB()) +} + +var keyCounter uint64 + +// we need to make this deterministic (same every test run), as encoded address size and thus gas cost, +// depends on the actual bytes (due to ugly CanonicalAddress encoding) +func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { + keyCounter++ + seed := make([]byte, 8) + binary.BigEndian.PutUint64(seed, keyCounter) + + key := ed25519.GenPrivKeyFromSecret(seed) + pub := key.PubKey() + addr := sdk.AccAddress(pub.Address()) + return key, pub, addr +} + +// encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) +func _createTestInput( + t testing.TB, + isCheckTx bool, + db dbm.DB, +) (sdk.Context, TestKeepers) { + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + distributiontypes.StoreKey, evmtypes.StoreKey, + ) + ms := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) + for _, v := range keys { + ms.MountStoreWithDB(v, storetypes.StoreTypeIAVL, db) + } + memKeys := storetypes.NewMemoryStoreKeys() + for _, v := range memKeys { + ms.MountStoreWithDB(v, storetypes.StoreTypeMemory, db) + } + + require.NoError(t, ms.LoadLatestVersion()) + + ctx := sdk.NewContext(ms, tmproto.Header{ + Height: 1, + Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC), + }, isCheckTx, log.NewNopLogger()).WithHeaderHash(make([]byte, 32)) + + encodingConfig := MakeEncodingConfig(t) + appCodec := encodingConfig.Codec + + maccPerms := map[string][]string{ // module account permissions + authtypes.FeeCollectorName: nil, + + // for testing + authtypes.Minter: {authtypes.Minter, authtypes.Burner}, + } + + ac := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + + erc20Keeper := new(evmkeeper.ERC20Keeper) + accountKeeper := authkeeper.NewAccountKeeper( + appCodec, + runtime.NewKVStoreService(keys[authtypes.StoreKey]), // target store + authtypes.ProtoBaseAccount, // prototype + maccPerms, + ac, + sdk.GetConfig().GetBech32AccountAddrPrefix(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + blockedAddrs := make(map[string]bool) + for acc := range maccPerms { + blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true + } + + bankKeeper := custombankkeeper.NewBaseKeeper( + appCodec, + runtime.NewKVStoreService(keys[banktypes.StoreKey]), + accountKeeper, + erc20Keeper, + blockedAddrs, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + require.NoError(t, bankKeeper.SetParams(ctx, banktypes.DefaultParams())) + + communityPoolKeeper := &MockCommunityPoolKeeper{} + evmKeeper := evmkeeper.NewKeeper( + ac, + appCodec, + runtime.NewKVStoreService(keys[evmtypes.StoreKey]), + accountKeeper, + communityPoolKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + EVMConfig.DefaultEVMConfig(), + ) + evmParams := evmtypes.DefaultParams() + require.NoError(t, evmKeeper.Params.Set(ctx, evmParams)) + require.NoError(t, evmKeeper.Initialize(ctx)) + + // set erc20 keeper + *erc20Keeper = *evmKeeper.ERC20Keeper().(*evmkeeper.ERC20Keeper) + + faucet := NewTestFaucet(t, ctx, bankKeeper, authtypes.Minter, initialTotalSupply()...) + + keepers := TestKeepers{ + AccountKeeper: accountKeeper, + CommunityPoolKeeper: communityPoolKeeper, + EVMKeeper: *evmKeeper, + BankKeeper: bankKeeper, + EncodingConfig: encodingConfig, + Faucet: faucet, + MultiStore: ms, + } + return ctx, keepers +} + +var _ evmtypes.CommunityPoolKeeper = &MockCommunityPoolKeeper{} + +type MockCommunityPoolKeeper struct { + CommunityPool sdk.Coins +} + +func (k *MockCommunityPoolKeeper) FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error { + k.CommunityPool = k.CommunityPool.Add(amount...) + + return nil +} diff --git a/x/bank/keeper/custom_msg_server.go b/x/bank/keeper/custom_msg_server.go new file mode 100644 index 0000000..b6d6159 --- /dev/null +++ b/x/bank/keeper/custom_msg_server.go @@ -0,0 +1,38 @@ +package keeper + +import ( + "context" + + errorsmod "cosmossdk.io/errors" + cosmosbank "github.com/cosmos/cosmos-sdk/x/bank/keeper" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + customtypes "github.com/initia-labs/minievm/x/bank/types" +) + +var _ customtypes.MsgServer = customMsgServer{} + +type customMsgServer struct { + cosmosbank.Keeper +} + +// NewCustomMsgServerImpl returns an implementation of the custom bank MsgServer interface +// for the provided Keeper. +func NewCustomMsgServerImpl(keeper cosmosbank.Keeper) customtypes.MsgServer { + return &customMsgServer{Keeper: keeper} +} + +// SetDenomMetadata implements customtypes.MsgServer. +func (ms customMsgServer) SetDenomMetadata(ctx context.Context, req *customtypes.MsgSetDenomMetadata) (*customtypes.MsgSetDenomMetadataResponse, error) { + if ms.GetAuthority() != req.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.GetAuthority(), req.Authority) + } + + if err := req.Metadata.Validate(); err != nil { + return nil, err + } + + ms.Keeper.SetDenomMetaData(ctx, req.Metadata) + + return &customtypes.MsgSetDenomMetadataResponse{}, nil +} diff --git a/x/bank/keeper/custom_msg_server_test.go b/x/bank/keeper/custom_msg_server_test.go new file mode 100644 index 0000000..e823b0f --- /dev/null +++ b/x/bank/keeper/custom_msg_server_test.go @@ -0,0 +1,41 @@ +package keeper_test + +import ( + "testing" + + cosmosbanktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/initia-labs/minievm/x/bank/keeper" + "github.com/initia-labs/minievm/x/bank/types" + "github.com/stretchr/testify/require" +) + +func Test_SetDenomMetadata(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + metadata := cosmosbanktypes.Metadata{ + Description: "hihi", + Base: "ufoo", + Display: "foo", + DenomUnits: []*cosmosbanktypes.DenomUnit{ + { + Denom: "ufoo", + Exponent: 0, + }, + { + Denom: "foo", + Exponent: 6, + }, + }, + Name: "foo coin", + Symbol: "foo", + } + _, err := keeper.NewCustomMsgServerImpl(input.BankKeeper).SetDenomMetadata(ctx, &types.MsgSetDenomMetadata{ + Authority: input.BankKeeper.GetAuthority(), + Metadata: metadata, + }) + require.NoError(t, err) + + _metadata, found := input.BankKeeper.GetDenomMetaData(ctx, "ufoo") + require.True(t, found) + require.Equal(t, metadata, _metadata) +} diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go new file mode 100644 index 0000000..46694df --- /dev/null +++ b/x/bank/keeper/genesis.go @@ -0,0 +1,61 @@ +package keeper + +import ( + "context" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// InitGenesis initializes the bank module's state from a given genesis state. +func (k BaseKeeper) InitGenesis(ctx context.Context, genState *types.GenesisState) { + if err := k.SetParams(ctx, genState.Params); err != nil { + panic(err) + } + + for _, se := range genState.GetAllSendEnabled() { + k.SetSendEnabled(ctx, se.Denom, se.Enabled) + } + + ac := k.ak.AddressCodec() + totalSupply := sdk.Coins{} + genState.Balances = types.SanitizeGenesisBalances(genState.Balances) + for _, balance := range genState.Balances { + addr, err := ac.StringToBytes(balance.GetAddress()) + if err != nil { + panic(err) + } + + if err := k.initBalances(ctx, addr, balance.Coins); err != nil { + panic(fmt.Errorf("error on setting balances %w", err)) + } + + totalSupply = totalSupply.Add(balance.Coins...) + } + + if !genState.Supply.Empty() && !genState.Supply.Equal(totalSupply) { + panic(fmt.Errorf("genesis supply is incorrect, expected %v, got %v", genState.Supply, totalSupply)) + } + + for _, meta := range genState.DenomMetadata { + k.SetDenomMetaData(ctx, meta) + } +} + +// ExportGenesis returns the bank module's genesis state. +func (k BaseKeeper) ExportGenesis(ctx context.Context) *types.GenesisState { + totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.PaginationMaxLimit}) + if err != nil { + panic(fmt.Errorf("unable to fetch total supply %v", err)) + } + + return types.NewGenesisState( + k.GetParams(ctx), + k.GetAccountsBalances(ctx), + totalSupply, + k.GetAllDenomMetaData(ctx), + k.GetAllSendEnabledEntries(ctx), + ) +} diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go new file mode 100644 index 0000000..27bd060 --- /dev/null +++ b/x/bank/keeper/genesis_test.go @@ -0,0 +1,112 @@ +package keeper_test + +import ( + "fmt" + "testing" + + "cosmossdk.io/math" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func TestExportGenesis(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + expectedMetadata := getTestMetadata() + expectedBalances, totalSupply := getTestBalancesAndSupply(input.Faucet.sender) + for i := range []int{1, 2} { + input.BankKeeper.SetDenomMetaData(ctx, expectedMetadata[i]) + accAddr, err1 := sdk.AccAddressFromBech32(expectedBalances[i].Address) + if err1 != nil { + panic(err1) + } + // set balances via mint and send + require.NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, expectedBalances[i].Coins)) + require.NoError(t, input.BankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, accAddr, expectedBalances[i].Coins)) + } + input.BankKeeper.SetParams(ctx, types.DefaultParams()) + + exportGenesis := input.BankKeeper.ExportGenesis(ctx) + + fmt.Println(expectedBalances, exportGenesis.Balances) + require.Len(t, exportGenesis.Params.SendEnabled, 0) + require.Equal(t, types.DefaultParams().DefaultSendEnabled, exportGenesis.Params.DefaultSendEnabled) + require.Equal(t, totalSupply, exportGenesis.Supply) + require.Equal(t, expectedBalances, exportGenesis.Balances) + require.Equal(t, expectedMetadata, exportGenesis.DenomMetadata) +} + +func getTestBalancesAndSupply(faucetAddr sdk.AccAddress) ([]types.Balance, sdk.Coins) { + addr1 := sdk.AccAddress([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) + addr2 := sdk.AccAddress([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}) + addr1Balance := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 10)) + addr2Balance := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 32), sdk.NewInt64Coin(testDenoms[0], 34)) + faucetBalance := initialTotalSupply() + + totalSupply := addr1Balance + totalSupply = totalSupply.Add(addr2Balance...) + totalSupply = totalSupply.Add(faucetBalance...) + + return []types.Balance{ + {Address: addr1.String(), Coins: addr1Balance}, + {Address: addr2.String(), Coins: addr2Balance}, + {Address: faucetAddr.String(), Coins: faucetBalance}, + }, totalSupply +} + +func Test_InitGenesis(t *testing.T) { + ctx, input := createDefaultTestInput(t) + m := types.Metadata{Description: bondDenom, Base: bondDenom, Display: bondDenom} + g := types.DefaultGenesisState() + g.DenomMetadata = []types.Metadata{m} + bk := input.BankKeeper + bk.InitGenesis(ctx, g) + + m2, found := bk.GetDenomMetaData(ctx, m.Base) + require.True(t, found) + require.Equal(t, m, m2) +} + +func TestTotalSupply(t *testing.T) { + // Prepare some test data. + defaultGenesis := types.DefaultGenesisState() + balances := []types.Balance{ + {Coins: sdk.NewCoins(sdk.NewCoin("foocoin", math.NewInt(1))), Address: "cosmos1f9xjhxm0plzrh9cskf4qee4pc2xwp0n0556gh0"}, + {Coins: sdk.NewCoins(sdk.NewCoin("barcoin", math.NewInt(1))), Address: "cosmos1t5u0jfg3ljsjrh2m9e47d4ny2hea7eehxrzdgd"}, + {Coins: sdk.NewCoins(sdk.NewCoin("foocoin", math.NewInt(10)), sdk.NewCoin("barcoin", math.NewInt(20))), Address: "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q"}, + } + totalSupply := sdk.NewCoins(sdk.NewCoin("foocoin", math.NewInt(11)), sdk.NewCoin("barcoin", math.NewInt(21))) + + testcases := map[string]struct { + genesis *types.GenesisState + expSupply sdk.Coins + }{ + "calculation matches genesis Supply field": { + types.NewGenesisState(defaultGenesis.Params, balances, totalSupply, defaultGenesis.DenomMetadata, defaultGenesis.SendEnabled), + totalSupply, + }, + "calculation is correct, empty genesis Supply field": { + types.NewGenesisState(defaultGenesis.Params, balances, nil, defaultGenesis.DenomMetadata, defaultGenesis.SendEnabled), + totalSupply, + }, + } + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + ctx, input := createDefaultTestInput(t) + input.BankKeeper.InitGenesis(ctx, tc.genesis) + totalSupply, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.PaginationMaxLimit}) + assert.NoError(t, err) + + // we need to exclude uinit and ustake due to faucet initial balance + for _, coin := range tc.expSupply { + assert.Equal(t, coin.Amount, totalSupply.AmountOf(coin.Denom)) + } + }) + } +} diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go new file mode 100644 index 0000000..3649bc8 --- /dev/null +++ b/x/bank/keeper/grpc_query.go @@ -0,0 +1,266 @@ +package keeper + +import ( + "context" + "errors" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "cosmossdk.io/collections" + "cosmossdk.io/store/prefix" + "github.com/cosmos/cosmos-sdk/runtime" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var _ types.QueryServer = BaseKeeper{} + +// Balance implements the Query/Balance gRPC method +func (k BaseKeeper) Balance(ctx context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + if req.Address == "" { + return nil, status.Error(codes.InvalidArgument, "address cannot be empty") + } + + if req.Denom == "" { + return nil, status.Error(codes.InvalidArgument, "invalid denom") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + addr, err := k.ak.AddressCodec().StringToBytes(req.Address) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid address: %s", err.Error()) + } + + balance := k.GetBalance(sdkCtx, addr, req.Denom) + + return &types.QueryBalanceResponse{Balance: &balance}, nil +} + +// AllBalances implements the Query/AllBalances gRPC method +func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalancesRequest) (*types.QueryAllBalancesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + if req.Address == "" { + return nil, status.Error(codes.InvalidArgument, "address cannot be empty") + } + + addr, err := k.ak.AddressCodec().StringToBytes(req.Address) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid address: %s", err.Error()) + } + + balances, pageRes, err := k.ek.GetPaginatedBalances(ctx, req.Pagination, addr) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load user stores: %s", err.Error()) + } + + // TODO - should we support resolve denom? + + return &types.QueryAllBalancesResponse{Balances: balances, Pagination: pageRes}, nil +} + +// SpendableBalances implements a gRPC query handler for retrieving an account's +// spendable balances. +func (k BaseKeeper) SpendableBalances(ctx context.Context, req *types.QuerySpendableBalancesRequest) (*types.QuerySpendableBalancesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + addr, err := k.ak.AddressCodec().StringToBytes(req.Address) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid address: %s", err.Error()) + } + + balances, pageRes, err := k.ek.GetPaginatedBalances(ctx, req.Pagination, addr) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load user stores: %s", err.Error()) + } + + return &types.QuerySpendableBalancesResponse{Balances: balances, Pagination: pageRes}, nil +} + +// SpendableBalanceByDenom implements a gRPC query handler for retrieving an account's +// spendable balance for a specific denom. +func (k BaseKeeper) SpendableBalanceByDenom(ctx context.Context, req *types.QuerySpendableBalanceByDenomRequest) (*types.QuerySpendableBalanceByDenomResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + addr, err := k.ak.AddressCodec().StringToBytes(req.Address) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid address: %s", err.Error()) + } + + if err := sdk.ValidateDenom(req.Denom); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + spendable := k.SpendableCoin(sdkCtx, addr, req.Denom) + + return &types.QuerySpendableBalanceByDenomResponse{Balance: &spendable}, nil +} + +// TotalSupply implements the Query/TotalSupply gRPC method +func (k BaseKeeper) TotalSupply(ctx context.Context, req *types.QueryTotalSupplyRequest) (*types.QueryTotalSupplyResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + totalSupply, pageRes, err := k.GetPaginatedTotalSupply(sdkCtx, req.Pagination) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryTotalSupplyResponse{Supply: totalSupply, Pagination: pageRes}, nil +} + +// SupplyOf implements the Query/SupplyOf gRPC method +func (k BaseKeeper) SupplyOf(c context.Context, req *types.QuerySupplyOfRequest) (*types.QuerySupplyOfResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + if req.Denom == "" { + return nil, status.Error(codes.InvalidArgument, "invalid denom") + } + + ctx := sdk.UnwrapSDKContext(c) + supply := k.GetSupply(ctx, req.Denom) + + return &types.QuerySupplyOfResponse{Amount: sdk.NewCoin(req.Denom, supply.Amount)}, nil +} + +// Params implements the gRPC service handler for querying x/bank parameters. +func (k BaseKeeper) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + params := k.GetParams(sdkCtx) + + return &types.QueryParamsResponse{Params: params}, nil +} + +// DenomsMetadata implements Query/DenomsMetadata gRPC method. +func (k BaseKeeper) DenomsMetadata(c context.Context, req *types.QueryDenomsMetadataRequest) (*types.QueryDenomsMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + kvStore := runtime.KVStoreAdapter(k.storeService.OpenKVStore(c)) + store := prefix.NewStore(kvStore, types.DenomMetadataPrefix) + + metadatas := []types.Metadata{} + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + var metadata types.Metadata + k.cdc.MustUnmarshal(value, &metadata) + + metadatas = append(metadatas, metadata) + return nil + }) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryDenomsMetadataResponse{ + Metadatas: metadatas, + Pagination: pageRes, + }, nil +} + +// DenomMetadata implements Query/DenomMetadata gRPC method. +func (k BaseKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if err := sdk.ValidateDenom(req.Denom); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + + metadata, found := k.GetDenomMetaData(ctx, req.Denom) + if !found { + var err error + metadata, err = k.ek.GetMetadata(ctx, req.Denom) + if errors.Is(err, collections.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "client metadata for denom %s", req.Denom) + } else if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + } + + return &types.QueryDenomMetadataResponse{ + Metadata: metadata, + }, nil +} + +// DenomMetadataByQueryString is identical to DenomMetadata query, but receives request via query string. +func (k BaseKeeper) DenomMetadataByQueryString(c context.Context, req *types.QueryDenomMetadataByQueryStringRequest) (*types.QueryDenomMetadataByQueryStringResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if err := sdk.ValidateDenom(req.Denom); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + + metadata, found := k.GetDenomMetaData(ctx, req.Denom) + if !found { + return nil, status.Errorf(codes.NotFound, "client metadata for denom %s", req.Denom) + } + + return &types.QueryDenomMetadataByQueryStringResponse{ + Metadata: metadata, + }, nil +} + +func (k BaseKeeper) DenomOwners( + goCtx context.Context, + req *types.QueryDenomOwnersRequest, +) (*types.QueryDenomOwnersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "not supported") +} + +func (k BaseKeeper) DenomOwnersByQuery(ctx context.Context, req *types.QueryDenomOwnersByQueryRequest) (*types.QueryDenomOwnersByQueryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "not supported") +} + +func (k BaseKeeper) SendEnabled(goCtx context.Context, req *types.QuerySendEnabledRequest) (*types.QuerySendEnabledResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + resp := &types.QuerySendEnabledResponse{} + if len(req.Denoms) > 0 { + for _, denom := range req.Denoms { + if se, ok := k.getSendEnabled(ctx, denom); ok { + resp.SendEnabled = append(resp.SendEnabled, types.NewSendEnabled(denom, se)) + } + } + } else { + results, pageResp, err := query.CollectionPaginate( + ctx, + k.MoveViewKeeper.SendEnabled, + req.Pagination, func(denom string, enabled bool) (*types.SendEnabled, error) { + return types.NewSendEnabled(denom, enabled), nil + }, + ) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + resp.SendEnabled = results + resp.Pagination = pageResp + } + + return resp, nil +} diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go new file mode 100644 index 0000000..f99f5a0 --- /dev/null +++ b/x/bank/keeper/grpc_query_test.go @@ -0,0 +1,150 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/stretchr/testify/require" +) + +func TestQueryBalance(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := testdata.KeyTestPubAddr() + + _, err := input.BankKeeper.Balance(ctx, &types.QueryBalanceRequest{}) + require.Error(t, err) + + _, err = input.BankKeeper.Balance(ctx, &types.QueryBalanceRequest{Address: addr.String()}) + require.Error(t, err) + + testDenom := testDenoms[0] + req := types.NewQueryBalanceRequest(addr, testDenom) + res, err := input.BankKeeper.Balance(ctx, req) + require.NoError(t, err) + require.NotNil(t, res) + require.True(t, res.Balance.IsZero()) + + origCoins := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(50)), sdk.NewCoin(bondDenom, math.NewInt(30))) + acc := input.AccountKeeper.NewAccountWithAddress(ctx, addr) + + input.AccountKeeper.SetAccount(ctx, acc) + input.Faucet.Fund(ctx, acc.GetAddress(), origCoins...) + + res, err = input.BankKeeper.Balance(ctx, req) + require.NoError(t, err) + require.NotNil(t, res) + require.True(t, res.Balance.IsEqual(sdk.NewCoin(testDenom, math.NewInt(50)))) +} + +func TestQueryAllBalances(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := testdata.KeyTestPubAddr() + _, err := input.BankKeeper.AllBalances(ctx, &types.QueryAllBalancesRequest{}) + require.Error(t, err) + + pageReq := &query.PageRequest{ + Key: nil, + Limit: 1, + CountTotal: false, + } + req := types.NewQueryAllBalancesRequest(addr, pageReq, false) + res, err := input.BankKeeper.AllBalances(ctx, req) + require.NoError(t, err) + require.NotNil(t, res) + require.True(t, res.Balances.IsZero()) + + testDenom := testDenoms[0] + rewardCoin := sdk.NewCoin(testDenom, math.NewInt(50)) + bondCoin := sdk.NewCoin(bondDenom, math.NewInt(30)) + + origCoins := sdk.NewCoins(rewardCoin, bondCoin) + acc := input.AccountKeeper.NewAccountWithAddress(ctx, addr) + + input.AccountKeeper.SetAccount(ctx, acc) + input.Faucet.Fund(ctx, acc.GetAddress(), origCoins...) + + res, err = input.BankKeeper.AllBalances(ctx, req) + require.NoError(t, err) + require.NotNil(t, res) + require.Equal(t, res.Balances.Len(), 1) + require.NotNil(t, res.Pagination.NextKey) + + t.Log("query second page with nextkey") + pageReq = &query.PageRequest{ + Key: res.Pagination.NextKey, + Limit: 1, + CountTotal: true, + } + req = types.NewQueryAllBalancesRequest(addr, pageReq, false) + res, err = input.BankKeeper.AllBalances(ctx, req) + require.NoError(t, err) + require.Equal(t, res.Balances.Len(), 1) + require.Nil(t, res.Pagination.NextKey) +} + +func TestQueryTotalSupply(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + mintCoins := sdk.NewCoins(sdk.NewInt64Coin("test", 400000000)) + expectedTotalSupply := initialTotalSupply().Add(mintCoins...) + require.NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, mintCoins)) + + res, err := input.BankKeeper.TotalSupply(ctx, &types.QueryTotalSupplyRequest{}) + require.NoError(t, err) + require.NotNil(t, res) + + require.Equal(t, expectedTotalSupply, res.Supply) +} + +func TestQueryTotalSupplyOf(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + test1Supply := sdk.NewInt64Coin("foo", 4000000) + test2Supply := sdk.NewInt64Coin("bar", 700000000) + mintCoins := sdk.NewCoins(test1Supply, test2Supply) + require. + NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, mintCoins)) + + _, err := input.BankKeeper.SupplyOf(ctx, &types.QuerySupplyOfRequest{}) + require.Error(t, err) + + res, err := input.BankKeeper.SupplyOf(ctx, &types.QuerySupplyOfRequest{Denom: test1Supply.Denom}) + require.NoError(t, err) + require.NotNil(t, res) + + require.Equal(t, test1Supply, res.Amount) +} + +func TestQueryParams(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + res, err := input.BankKeeper.Params(ctx, &types.QueryParamsRequest{}) + require.NoError(t, err) + require.NotNil(t, res) + require.Equal(t, input.BankKeeper.GetParams(ctx), res.GetParams()) +} + +func TestQueryDenomMetadata(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + res, err := input.BankKeeper.DenomMetadata(ctx, &types.QueryDenomMetadataRequest{ + Denom: bondDenom, + }) + require.NoError(t, err) + metadata := res.Metadata + require.Equal(t, sdk.DefaultBondDenom, metadata.Base) + require.Equal(t, sdk.DefaultBondDenom, metadata.Display) + require.Equal(t, sdk.DefaultBondDenom, metadata.Name) + require.Equal(t, []*types.DenomUnit{ + { + Denom: bondDenom, + Exponent: 0, + }, + }, metadata.DenomUnits) +} diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go new file mode 100644 index 0000000..e18a143 --- /dev/null +++ b/x/bank/keeper/keeper.go @@ -0,0 +1,376 @@ +package keeper + +import ( + "context" + "fmt" + + "cosmossdk.io/core/store" + "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + cosmosbank "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var _ cosmosbank.Keeper = (*BaseKeeper)(nil) + +// BaseKeeper manages transfers between accounts. It implements the Keeper interface. +type BaseKeeper struct { + MoveSendKeeper + + ak types.AccountKeeper + cdc codec.BinaryCodec + storeService store.KVStoreService + mintCoinsRestrictionFn types.MintingRestrictionFn +} + +// GetPaginatedTotalSupply queries for the supply, ignoring 0 coins, with a given pagination +func (k BaseKeeper) GetPaginatedTotalSupply(ctx context.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) { + return k.ek.GetPaginatedSupply(ctx, pagination) +} + +// NewBaseKeeper returns a new BaseKeeper object with a given codec, dedicated +// store key, an AccountKeeper implementation, and a parameter Subspace used to +// store and fetch module parameters. The BaseKeeper also accepts a +// blocklist map. This blocklist describes the set of addresses that are not allowed +// to receive funds through direct and explicit actions, for example, by using a MsgSend or +// by using a SendCoinsFromModuleToAccount execution. +func NewBaseKeeper( + cdc codec.BinaryCodec, + storeService store.KVStoreService, + ak types.AccountKeeper, + ek evmtypes.IERC20Keeper, + blockedAddrs map[string]bool, + authority string, +) BaseKeeper { + if _, err := ak.AddressCodec().StringToBytes(authority); err != nil { + panic(fmt.Errorf("invalid bank authority address: %w", err)) + } + + return BaseKeeper{ + MoveSendKeeper: NewMoveSendKeeper(cdc, storeService, ak, ek, blockedAddrs, authority), + ak: ak, + cdc: cdc, + storeService: storeService, + mintCoinsRestrictionFn: types.NoOpMintingRestrictionFn, + } +} + +// DO NOT USE IT +func (k BaseKeeper) WithMintCoinsRestriction(check types.MintingRestrictionFn) cosmosbank.BaseKeeper { + panic("not supported") +} + +// WithMintCoinsRestrictionV2 restricts the bank Keeper used within a specific module to +// have restricted permissions on minting via function passed in parameter. +// Previous restriction functions can be nested as such: +// +// bankKeeper.WithMintCoinsRestriction(restriction1).WithMintCoinsRestriction(restriction2) +func (k BaseKeeper) WithMintCoinsRestrictionV2(check types.MintingRestrictionFn) BaseKeeper { + k.mintCoinsRestrictionFn = check + return k +} + +// DelegateCoins performs delegation by deducting amt coins from an account with +// address addr. The coins are then transferred from the delegator +// address to a ModuleAccount address. If any of the delegation amounts are negative, +// an error is returned. +func (k BaseKeeper) DelegateCoins(ctx context.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error { + moduleAcc := k.ak.GetAccount(ctx, moduleAccAddr) + if moduleAcc == nil { + return errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr) + } + + if !amt.IsValid() { + return errors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) + } + + // transfer coins to module account + err := k.ek.SendCoins(ctx, delegatorAddr, moduleAccAddr, amt) + if err != nil { + return err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // emit coin spent event + sdkCtx.EventManager().EmitEvent( + types.NewCoinSpentEvent(delegatorAddr, amt), + ) + + // emit coin received event + sdkCtx.EventManager().EmitEvent( + types.NewCoinReceivedEvent(moduleAccAddr, amt), + ) + + return nil +} + +// UndelegateCoins performs undelegation by crediting amt coins to an account with +// address addr. The coins are then transferred from a ModuleAccount +// address to the delegator address. If any of the undelegation amounts are +// negative, an error is returned. +func (k BaseKeeper) UndelegateCoins(ctx context.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error { + moduleAcc := k.ak.GetAccount(ctx, moduleAccAddr) + if moduleAcc == nil { + return errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr) + } + + if !amt.IsValid() { + return errors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) + } + + // transfer coins to delegator account + err := k.ek.SendCoins(ctx, moduleAccAddr, delegatorAddr, amt) + if err != nil { + return err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // emit coin spent event + sdkCtx.EventManager().EmitEvent( + types.NewCoinSpentEvent(moduleAccAddr, amt), + ) + + // emit coin received event + sdkCtx.EventManager().EmitEvent( + types.NewCoinReceivedEvent(delegatorAddr, amt), + ) + + return nil +} + +// GetSupply retrieves the Supply from store +func (k BaseKeeper) GetSupply(ctx context.Context, denom string) sdk.Coin { + amount, err := k.ek.GetSupply(ctx, denom) + if err != nil { + panic(err) + } + + return sdk.Coin{ + Denom: denom, + Amount: amount, + } +} + +// HasSupply checks if the supply coin exists in store. +func (k BaseKeeper) HasSupply(ctx context.Context, denom string) bool { + ok, err := k.ek.HasSupply(ctx, denom) + if err != nil { + panic(err) + } + + return ok +} + +// GetDenomMetaData retrieves the denomination metadata. returns the metadata and true if the denom exists, +// false otherwise. +func (k BaseKeeper) GetDenomMetaData(ctx context.Context, denom string) (types.Metadata, bool) { + m, err := k.MoveViewKeeper.DenomMetadata.Get(ctx, denom) + return m, err == nil +} + +// HasDenomMetaData checks if the denomination metadata exists in store. +func (k BaseKeeper) HasDenomMetaData(ctx context.Context, denom string) bool { + has, err := k.MoveViewKeeper.DenomMetadata.Has(ctx, denom) + return has && err == nil +} + +// GetAllDenomMetaData retrieves all denominations metadata +func (k BaseKeeper) GetAllDenomMetaData(ctx context.Context) []types.Metadata { + denomMetaData := make([]types.Metadata, 0) + k.IterateAllDenomMetaData(ctx, func(metadata types.Metadata) bool { + denomMetaData = append(denomMetaData, metadata) + return false + }) + + return denomMetaData +} + +// IterateAllDenomMetaData iterates over all the denominations metadata and +// provides the metadata to a callback. If true is returned from the +// callback, iteration is halted. +func (k BaseKeeper) IterateAllDenomMetaData(ctx context.Context, cb func(types.Metadata) bool) { + err := k.MoveViewKeeper.DenomMetadata.Walk(ctx, nil, func(_ string, metadata types.Metadata) (stop bool, err error) { + return cb(metadata), nil + }) + if err != nil { + panic(err) + } +} + +// SetDenomMetaData sets the denominations metadata +func (k BaseKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types.Metadata) { + _ = k.MoveViewKeeper.DenomMetadata.Set(ctx, denomMetaData.Base, denomMetaData) +} + +// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress. +// It will panic if the module account does not exist. An error is returned if +// the recipient address is black-listed or if sending the tokens fails. +func (k BaseKeeper) SendCoinsFromModuleToAccount( + ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, +) error { + senderAddr := k.ak.GetModuleAddress(senderModule) + if senderAddr == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + if k.BlockedAddr(recipientAddr) { + return errors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", recipientAddr) + } + + return k.SendCoins(ctx, senderAddr, recipientAddr, amt) +} + +// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another. +// It will panic if either module account does not exist. +func (k BaseKeeper) SendCoinsFromModuleToModule( + ctx context.Context, senderModule, recipientModule string, amt sdk.Coins, +) error { + senderAddr := k.ak.GetModuleAddress(senderModule) + if senderAddr == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + return k.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount. +// It will panic if the module account does not exist. +func (k BaseKeeper) SendCoinsFromAccountToModule( + ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, +) error { + recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + return k.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +// DelegateCoinsFromAccountToModule delegates coins and transfers them from a +// delegator account to a module account. It will panic if the module account +// does not exist or is unauthorized. +func (k BaseKeeper) DelegateCoinsFromAccountToModule( + ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, +) error { + recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + if !recipientAcc.HasPermission(authtypes.Staking) { + panic(errors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to receive delegated coins", recipientModule)) + } + + return k.DelegateCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +// UndelegateCoinsFromModuleToAccount undelegates the unbonding coins and transfers +// them from a module account to the delegator account. It will panic if the +// module account does not exist or is unauthorized. +func (k BaseKeeper) UndelegateCoinsFromModuleToAccount( + ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, +) error { + acc := k.ak.GetModuleAccount(ctx, senderModule) + if acc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + if !acc.HasPermission(authtypes.Staking) { + panic(errors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to undelegate coins", senderModule)) + } + + return k.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt) +} + +// MintCoins creates new coins from thin air and adds it to the module account. +// It will panic if the module account does not exist or is unauthorized. +func (k BaseKeeper) MintCoins(ctx context.Context, moduleName string, amounts sdk.Coins) error { + err := k.mintCoinsRestrictionFn(ctx, amounts) + if err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Module %q attempted to mint coins %s it doesn't have permission for, error %v", moduleName, amounts, err)) + return err + } + acc := k.ak.GetModuleAccount(ctx, moduleName) + if acc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) + } + + if !acc.HasPermission(authtypes.Minter) { + panic(errors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)) + } + + if err := amounts.Validate(); err != nil { + return errors.Wrap(sdkerrors.ErrInvalidCoins, err.Error()) + } + + err = k.ek.MintCoins(ctx, acc.GetAddress(), amounts) + if err != nil { + return err + } + + logger := k.Logger(ctx) + logger.Info("minted coins from module account", "amount", amounts.String(), "from", moduleName) + + // emit mint event + sdkCtx := sdk.UnwrapSDKContext(ctx) + sdkCtx.EventManager().EmitEvent( + types.NewCoinMintEvent(acc.GetAddress(), amounts), + ) + + return nil +} + +// BurnCoins burns coins deletes coins from the balance of the module account. +// It will panic if the module account does not exist or is unauthorized. +func (k BaseKeeper) BurnCoins(ctx context.Context, moduleName string, amounts sdk.Coins) error { + acc := k.ak.GetModuleAccount(ctx, moduleName) + if acc == nil { + panic(errors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) + } + + if !acc.HasPermission(authtypes.Burner) { + panic(errors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to burn tokens", moduleName)) + } + + err := k.ek.BurnCoins(ctx, acc.GetAddress(), amounts) + if err != nil { + return err + } + + logger := k.Logger(ctx) + logger.Info("burned tokens from module account", "amount", amounts.String(), "from", moduleName) + + // emit burn event + sdkCtx := sdk.UnwrapSDKContext(ctx) + sdkCtx.EventManager().EmitEvent( + types.NewCoinBurnEvent(acc.GetAddress(), amounts), + ) + + return nil +} + +// IterateTotalSupply iterates over the total supply calling the given cb (callback) function +// with the balance of each coin. +// The iteration stops if the callback returns true. +func (k MoveViewKeeper) IterateTotalSupply(ctx context.Context, cb func(sdk.Coin) bool) { + err := k.ek.IterateSupply(ctx, func(supply sdk.Coin) (bool, error) { + return cb(supply), nil + }) + if err != nil { + panic(err) + } +} diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go new file mode 100644 index 0000000..11a2c84 --- /dev/null +++ b/x/bank/keeper/keeper_test.go @@ -0,0 +1,400 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + abci "github.com/cometbft/cometbft/abci/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/stretchr/testify/require" +) + +func getCoinsByName(ctx sdk.Context, bk keeper.Keeper, ak types.AccountKeeper, moduleName string) sdk.Coins { + moduleAddress := ak.GetModuleAddress(moduleName) + macc := ak.GetAccount(ctx, moduleAddress) + if macc == nil { + return sdk.Coins(nil) + } + + return bk.GetAllBalances(ctx, macc.GetAddress()) +} + +func getTestMetadata() []types.Metadata { + return []types.Metadata{ + { + Name: "Initia INIT", + Symbol: "INIT", + Description: "The native reward token of the Initia Network.", + DenomUnits: []*types.DenomUnit{ + {Denom: "uinit", Exponent: uint32(0), Aliases: []string{"microinit"}}, + {Denom: "minit", Exponent: uint32(3), Aliases: []string{"milliinit"}}, + {Denom: "init", Exponent: uint32(6), Aliases: nil}, + }, + Base: "uinit", + Display: "init", + }, + { + Name: "Initia LP", + Symbol: "LP", + Description: "The native staking token of the Initia Network.", + DenomUnits: []*types.DenomUnit{ + {Denom: "ulp", Exponent: uint32(0), Aliases: []string{"microlp"}}, + {Denom: "mlp", Exponent: uint32(3), Aliases: []string{"milliop"}}, + {Denom: "lp", Exponent: uint32(6), Aliases: nil}, + }, + Base: "ulp", + Display: "lp", + }, + } +} + +func TestSupply(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + totalSupply := initialTotalSupply() + require.NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, totalSupply)) + + total, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + require.Equal(t, totalSupply.Add(totalSupply...), total) + + // burning all supplied tokens + // BurnCoins is not actually burning the token, but transfer to community pool + err = input.BankKeeper.BurnCoins(ctx, authtypes.Minter, totalSupply) + require.NoError(t, err) + + total, _, err = input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + require.Equal(t, totalSupply, total) +} + +func TestSendCoinsFromModuleToAccount_Blacklist(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + testDenom := testDenoms[0] + coins := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + require.NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, coins)) + require.Error(t, input.BankKeeper.SendCoinsFromModuleToAccount( + ctx, authtypes.Minter, authtypes.NewModuleAddress(authtypes.FeeCollectorName), coins, + )) +} + +func TestSupply_SendCoins(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + testDenom := testDenoms[0] + coins := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + input.BankKeeper.MintCoins(ctx, authtypes.Minter, coins) + + require.Panics(t, func() { + _ = input.BankKeeper.SendCoinsFromModuleToModule(ctx, "", authtypes.Minter, coins) // nolint:errcheck + }) + + require.Panics(t, func() { + _ = input.BankKeeper.SendCoinsFromModuleToModule(ctx, authtypes.Minter, "", coins) // nolint:errcheck + }) + + require.Panics(t, func() { + _ = input.BankKeeper.SendCoinsFromModuleToAccount(ctx, "", addrs[0], coins) // nolint:errcheck + }) + + // not enough balance + require.Error(t, input.BankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, addrs[0], coins.Add(coins...))) + + require.NoError(t, input.BankKeeper.SendCoinsFromModuleToModule(ctx, authtypes.Minter, authtypes.FeeCollectorName, coins)) + require.Equal(t, sdk.NewCoins().String(), getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.Minter).String()) + require.Equal(t, coins, getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.FeeCollectorName)) + + require.NoError(t, input.BankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, addrs[0], coins)) + require.Equal(t, sdk.NewCoins().String(), getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.FeeCollectorName).String()) + require.Equal(t, coins, input.BankKeeper.GetAllBalances(ctx, addrs[0])) + + require.NoError(t, input.BankKeeper.SendCoinsFromAccountToModule(ctx, addrs[0], authtypes.FeeCollectorName, coins)) + require.Equal(t, sdk.NewCoins().String(), input.BankKeeper.GetAllBalances(ctx, addrs[0]).String()) + require.Equal(t, coins, getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.FeeCollectorName)) +} + +func TestSupply_MintCoins(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + initialSupply, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + + testDenom := testDenoms[0] + coins := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + require.Panics(t, func() { input.BankKeeper.MintCoins(ctx, "", coins) }, "no module account") // nolint:errcheck + require.Panics(t, func() { input.BankKeeper.MintCoins(ctx, authtypes.FeeCollectorName, coins) }, "invalid permission") // nolint:errcheck + require.Error(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: math.NewInt(-10)}})) + + err = input.BankKeeper.MintCoins(ctx, authtypes.Minter, coins) + require.NoError(t, err) + + require.Equal(t, coins, getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.Minter)) + totalSupply, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + + require.Equal(t, initialSupply.Add(coins...), totalSupply) +} + +func TestSupply_BurnCoins(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + testDenom := testDenoms[0] + coins := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + + // inflate supply + require. + NoError(t, input.BankKeeper.MintCoins(ctx, authtypes.Minter, coins)) + supplyAfterInflation, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + + require.Panics(t, func() { input.BankKeeper.BurnCoins(ctx, "", coins) }, "no module account") // nolint:errcheck + require.Panics(t, func() { input.BankKeeper.BurnCoins(ctx, authtypes.FeeCollectorName, coins) }, "invalid permission") // nolint:errcheck + err = input.BankKeeper.BurnCoins(ctx, authtypes.Minter, supplyAfterInflation) + require.Error(t, err, "insufficient coins") + + err = input.BankKeeper.BurnCoins(ctx, authtypes.Minter, coins) + require.NoError(t, err) + supplyAfterBurn, _, err := input.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + require.NoError(t, err) + require.Equal(t, sdk.NewCoins().String(), getCoinsByName(ctx, input.BankKeeper, input.AccountKeeper, authtypes.Minter).String()) + require.Equal(t, supplyAfterInflation, supplyAfterBurn.Add(coins...)) +} + +func TestSendCoinsNewAccount(t *testing.T) { + ctx, input := createDefaultTestInput(t) + testDenom := testDenoms[0] + balances := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + + addr1 := sdk.AccAddress([]byte("addr1_______________")) + acc1 := input.AccountKeeper.NewAccountWithAddress(ctx, addr1) + input.AccountKeeper.SetAccount(ctx, acc1) + input.Faucet.Fund(ctx, addr1, balances...) + + acc1Balances := input.BankKeeper.GetAllBalances(ctx, addr1) + require.Equal(t, balances, acc1Balances) + + addr2 := sdk.AccAddress([]byte("addr2_______________")) + + require.Nil(t, input.AccountKeeper.GetAccount(ctx, addr2)) + input.BankKeeper.GetAllBalances(ctx, addr2) + require.Empty(t, input.BankKeeper.GetAllBalances(ctx, addr2)) + + sendAmt := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(50))) + require.NoError(t, input.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) + + acc2Balances := input.BankKeeper.GetAllBalances(ctx, addr2) + acc1Balances = input.BankKeeper.GetAllBalances(ctx, addr1) + require.Equal(t, sendAmt, acc2Balances) + updatedAcc1Bal := balances.Sub(sendAmt...) + require.Len(t, acc1Balances, len(updatedAcc1Bal)) + require.Equal(t, acc1Balances, updatedAcc1Bal) + require.NotNil(t, input.AccountKeeper.GetAccount(ctx, addr2)) +} + +func TestSendCoins(t *testing.T) { + ctx, input := createDefaultTestInput(t) + testDenom := testDenoms[0] + balances := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100)), sdk.NewCoin(bondDenom, math.NewInt(100))) + + addr1 := sdk.AccAddress("addr1_______________") + acc1 := input.AccountKeeper.NewAccountWithAddress(ctx, addr1) + input.AccountKeeper.SetAccount(ctx, acc1) + + addr2 := sdk.AccAddress("addr2_______________") + acc2 := input.AccountKeeper.NewAccountWithAddress(ctx, addr2) + input.AccountKeeper.SetAccount(ctx, acc2) + input.Faucet.Fund(ctx, addr2, balances...) + + sendAmt := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(50)), sdk.NewCoin(bondDenom, math.NewInt(25))) + require.Error(t, input.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) + + input.Faucet.Fund(ctx, addr1, balances...) + require.NoError(t, input.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) + + acc1Balances := input.BankKeeper.GetAllBalances(ctx, addr1) + expected := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(50)), sdk.NewCoin(bondDenom, math.NewInt(75))) + require.Equal(t, expected, acc1Balances) + + acc2Balances := input.BankKeeper.GetAllBalances(ctx, addr2) + expected = sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(150)), sdk.NewCoin(bondDenom, math.NewInt(125))) + require.Equal(t, expected, acc2Balances) + + var coins sdk.Coins + input.BankKeeper.IterateAccountBalances(ctx, addr1, func(c sdk.Coin) (stop bool) { + coins = append(coins, c) + return false + }) + + require.Len(t, coins, 2) + require.Equal(t, acc1Balances, coins.Sort(), "expected only bar coins in the account balance, got: %v", coins) +} + +func TestValidateBalance(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + addr1 := sdk.AccAddress([]byte("addr1_______________")) + require.NoError(t, input.BankKeeper.ValidateBalance(ctx, addr1)) + + acc := input.AccountKeeper.NewAccountWithAddress(ctx, addr1) + input.AccountKeeper.SetAccount(ctx, acc) + + balances := sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(100))) + input.Faucet.Fund(ctx, addr1, balances...) + require.NoError(t, input.BankKeeper.ValidateBalance(ctx, addr1)) +} + +func TestSendEnabled(t *testing.T) { + ctx, input := createDefaultTestInput(t) + enabled := true + params := types.DefaultParams() + require.Equal(t, enabled, params.DefaultSendEnabled) + + input.BankKeeper.SetParams(ctx, params) + + bondCoin := sdk.NewCoin(bondDenom, math.OneInt()) + + testDenom := testDenoms[0] + testCoin := sdk.NewCoin(testDenom, math.OneInt()) + + // assert with default (all denom) send enabled both Bar and Bond Denom are enabled + require.Equal(t, enabled, input.BankKeeper.IsSendEnabledCoin(ctx, testCoin)) + require.Equal(t, enabled, input.BankKeeper.IsSendEnabledCoin(ctx, bondCoin)) + + // Both coins should be send enabled. + err := input.BankKeeper.IsSendEnabledCoins(ctx, testCoin, bondCoin) + require.NoError(t, err) + + // Set default send_enabled to !enabled, add a reward denom that overrides default as enabled + params.DefaultSendEnabled = !enabled + require.NoError(t, input.BankKeeper.SetParams(ctx, params)) + input.BankKeeper.SetSendEnabled(ctx, testCoin.Denom, enabled) + + // Expect our specific override to be enabled, others to be !enabled. + require.Equal(t, enabled, input.BankKeeper.IsSendEnabledCoin(ctx, testCoin)) + require.Equal(t, !enabled, input.BankKeeper.IsSendEnabledCoin(ctx, bondCoin)) + + // Foo coin should be send enabled. + err = input.BankKeeper.IsSendEnabledCoins(ctx, testCoin) + require.NoError(t, err) + + // Expect an error when one coin is not send enabled. + err = input.BankKeeper.IsSendEnabledCoins(ctx, testCoin, bondCoin) + require.Error(t, err) + + // Expect an error when all coins are not send enabled. + err = input.BankKeeper.IsSendEnabledCoins(ctx, bondCoin) + require.Error(t, err) +} + +func TestHasBalance(t *testing.T) { + ctx, input := createDefaultTestInput(t) + addr := sdk.AccAddress([]byte("addr1_______________")) + + acc := input.AccountKeeper.NewAccountWithAddress(ctx, addr) + input.AccountKeeper.SetAccount(ctx, acc) + + testDenom := testDenoms[0] + balances := sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100))) + require.False(t, input.BankKeeper.HasBalance(ctx, addr, sdk.NewCoin(testDenom, math.NewInt(99)))) + + input.Faucet.Fund(ctx, addr, balances...) + require.False(t, input.BankKeeper.HasBalance(ctx, addr, sdk.NewCoin(testDenom, math.NewInt(101)))) + require.True(t, input.BankKeeper.HasBalance(ctx, addr, sdk.NewCoin(testDenom, math.NewInt(100)))) + require.True(t, input.BankKeeper.HasBalance(ctx, addr, sdk.NewCoin(testDenom, math.NewInt(1)))) +} + +func TestMsgSendEvents(t *testing.T) { + ctx, input := createDefaultTestInput(t) + addr := sdk.AccAddress([]byte("addr1_______________")) + addr2 := sdk.AccAddress([]byte("addr2_______________")) + acc := input.AccountKeeper.NewAccountWithAddress(ctx, addr) + + input.AccountKeeper.SetAccount(ctx, acc) + + testDenom := testDenoms[0] + newCoins := sdk.NewCoins(sdk.NewInt64Coin(testDenom, 50)) + input.Faucet.Fund(ctx, addr, newCoins...) + + ctx = ctx.WithEventManager(sdk.NewEventManager()) + require.NoError(t, input.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)) + event1 := sdk.Event{ + Type: types.EventTypeTransfer, + Attributes: []abci.EventAttribute{}, + } + event1.Attributes = append( + event1.Attributes, + abci.EventAttribute{Key: types.AttributeKeyRecipient, Value: addr2.String()}, + ) + event1.Attributes = append( + event1.Attributes, + abci.EventAttribute{Key: types.AttributeKeySender, Value: addr.String()}, + ) + event1.Attributes = append( + event1.Attributes, + abci.EventAttribute{Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, + ) + + event2 := sdk.Event{ + Type: sdk.EventTypeMessage, + Attributes: []abci.EventAttribute{}, + } + event2.Attributes = append( + event2.Attributes, + abci.EventAttribute{Key: types.AttributeKeySender, Value: addr.String()}, + ) + + events := ctx.EventManager().ABCIEvents() + require.Equal(t, abci.Event(event1), events[len(events)-2]) + require.Equal(t, abci.Event(event2), events[len(events)-1]) +} + +func TestSetDenomMetaData(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + metadata := getTestMetadata() + + for i := range []int{1, 2} { + input.BankKeeper.SetDenomMetaData(ctx, metadata[i]) + } + + actualMetadata, found := input.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base) + require.True(t, found) + require.Equal(t, metadata[1].GetBase(), actualMetadata.GetBase()) + require.Equal(t, metadata[1].GetDisplay(), actualMetadata.GetDisplay()) + require.Equal(t, metadata[1].GetDescription(), actualMetadata.GetDescription()) + require.Equal(t, metadata[1].GetDenomUnits()[1].GetDenom(), actualMetadata.GetDenomUnits()[1].GetDenom()) + require.Equal(t, metadata[1].GetDenomUnits()[1].GetExponent(), actualMetadata.GetDenomUnits()[1].GetExponent()) + require.Equal(t, metadata[1].GetDenomUnits()[1].GetAliases(), actualMetadata.GetDenomUnits()[1].GetAliases()) +} + +func TestIterateAllDenomMetaData(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + expectedMetadata := getTestMetadata() + // set metadata + for i := range []int{1, 2} { + input.BankKeeper.SetDenomMetaData(ctx, expectedMetadata[i]) + } + // retrieve metadata + actualMetadata := make([]types.Metadata, 0) + input.BankKeeper.IterateAllDenomMetaData(ctx, func(metadata types.Metadata) bool { + actualMetadata = append(actualMetadata, metadata) + return false + }) + // execute checks + for i := range []int{1, 2} { + require.Equal(t, expectedMetadata[i].GetBase(), actualMetadata[i].GetBase()) + require.Equal(t, expectedMetadata[i].GetDisplay(), actualMetadata[i].GetDisplay()) + require.Equal(t, expectedMetadata[i].GetDescription(), actualMetadata[i].GetDescription()) + require.Equal(t, expectedMetadata[i].GetDenomUnits()[1].GetDenom(), actualMetadata[i].GetDenomUnits()[1].GetDenom()) + require.Equal(t, expectedMetadata[i].GetDenomUnits()[1].GetExponent(), actualMetadata[i].GetDenomUnits()[1].GetExponent()) + require.Equal(t, expectedMetadata[i].GetDenomUnits()[1].GetAliases(), actualMetadata[i].GetDenomUnits()[1].GetAliases()) + } +} diff --git a/x/bank/keeper/msg_server.go b/x/bank/keeper/msg_server.go new file mode 100644 index 0000000..092bf90 --- /dev/null +++ b/x/bank/keeper/msg_server.go @@ -0,0 +1,141 @@ +package keeper + +import ( + "context" + + "github.com/hashicorp/go-metrics" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + cosmosbank "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +type msgServer struct { + cosmosbank.Keeper +} + +var _ types.MsgServer = msgServer{} + +// NewMsgServerImpl returns an implementation of the bank MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper cosmosbank.Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +func (k msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) { + var ( + from, to []byte + err error + ) + + if base, ok := k.Keeper.(BaseKeeper); ok { + from, err = base.ak.AddressCodec().StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid from address: %s", err) + } + to, err = base.ak.AddressCodec().StringToBytes(msg.ToAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid to address: %s", err) + } + } else { + return nil, sdkerrors.ErrInvalidRequest.Wrapf("invalid keeper type: %T", k.Keeper) + } + + if !msg.Amount.IsValid() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + if !msg.Amount.IsAllPositive() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { + return nil, err + } + + if k.BlockedAddr(to) { + return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) + } + + err = k.SendCoins(ctx, from, to, msg.Amount) + if err != nil { + return nil, err + } + + defer func() { + for _, a := range msg.Amount { + if a.Amount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "send"}, + float32(a.Amount.Int64()), + []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, + ) + } + } + }() + + return &types.MsgSendResponse{}, nil +} + +func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*types.MsgMultiSendResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "not supported") +} + +func (k msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.GetAuthority() != req.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.GetAuthority(), req.Authority) + } + + if err := req.Params.Validate(); err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.SetParams(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} + +func (k msgServer) SetSendEnabled(goCtx context.Context, msg *types.MsgSetSendEnabled) (*types.MsgSetSendEnabledResponse, error) { + if k.GetAuthority() != msg.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.GetAuthority(), msg.Authority) + } + + seen := map[string]bool{} + for _, se := range msg.SendEnabled { + if _, alreadySeen := seen[se.Denom]; alreadySeen { + return nil, sdkerrors.ErrInvalidRequest.Wrapf("duplicate denom entries found for %q", se.Denom) + } + + seen[se.Denom] = true + + if err := se.Validate(); err != nil { + return nil, sdkerrors.ErrInvalidRequest.Wrapf("invalid SendEnabled denom %q: %s", se.Denom, err) + } + } + + for _, denom := range msg.UseDefaultFor { + if err := sdk.ValidateDenom(denom); err != nil { + return nil, sdkerrors.ErrInvalidRequest.Wrapf("invalid UseDefaultFor denom %q: %s", denom, err) + } + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if len(msg.SendEnabled) > 0 { + k.SetAllSendEnabled(ctx, msg.SendEnabled) + } + if len(msg.UseDefaultFor) > 0 { + k.DeleteSendEnabled(ctx, msg.UseDefaultFor...) + } + + return &types.MsgSetSendEnabledResponse{}, nil +} diff --git a/x/bank/keeper/msg_server_test.go b/x/bank/keeper/msg_server_test.go new file mode 100644 index 0000000..800c5d3 --- /dev/null +++ b/x/bank/keeper/msg_server_test.go @@ -0,0 +1,279 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + bankkeeper "github.com/initia-labs/minievm/x/bank/keeper" +) + +var govAcc = authtypes.NewEmptyModuleAccount(govtypes.ModuleName, authtypes.Minter) + +func TestMsgUpdateParams(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + // default params + params := banktypes.DefaultParams() + + testCases := []struct { + name string + input *banktypes.MsgUpdateParams + expErr bool + expErrMsg string + }{ + { + name: "invalid authority", + input: &banktypes.MsgUpdateParams{ + Authority: "invalid", + Params: params, + }, + expErr: true, + expErrMsg: "invalid authority", + }, + { + name: "send enabled param", + input: &banktypes.MsgUpdateParams{ + Authority: input.BankKeeper.GetAuthority(), + Params: banktypes.Params{ + SendEnabled: []*banktypes.SendEnabled{ + {Denom: "foo", Enabled: true}, + }, + }, + }, + expErr: true, + expErrMsg: "use of send_enabled in params is no longer supported", + }, + { + name: "all good", + input: &banktypes.MsgUpdateParams{ + Authority: input.BankKeeper.GetAuthority(), + Params: params, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := bankkeeper.NewMsgServerImpl(input.BankKeeper).UpdateParams(ctx, tc.input) + + if tc.expErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErrMsg) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgSend(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + origCoins := sdk.NewCoins(sdk.NewInt64Coin("sendableCoin", 100)) + input.BankKeeper.SetSendEnabled(ctx, origCoins.Denoms()[0], true) + input.BankKeeper.GetBlockedAddresses() + atom0 := sdk.NewCoins(sdk.NewInt64Coin("atom", 0)) + atom123eth0 := sdk.Coins{sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 0)} + + testCases := []struct { + name string + input *banktypes.MsgSend + expErr bool + expErrMsg string + }{ + { + name: "invalid send to blocked address", + input: &banktypes.MsgSend{ + FromAddress: addrs[0].String(), + ToAddress: authtypes.NewModuleAddress(authtypes.FeeCollectorName).String(), + Amount: origCoins, + }, + expErr: true, + expErrMsg: "is not allowed to receive funds", + }, + { + name: "invalid coins", + input: &banktypes.MsgSend{ + FromAddress: addrs[0].String(), + ToAddress: addrs[1].String(), + Amount: atom0, + }, + expErr: true, + expErrMsg: "invalid coins", + }, + { + name: "123atom,0eth: invalid coins", + input: &banktypes.MsgSend{ + FromAddress: addrs[0].String(), + ToAddress: addrs[1].String(), + Amount: atom123eth0, + }, + expErr: true, + expErrMsg: "123atom,0eth: invalid coins", + }, + { + name: "invalid from address: empty address string is not allowed: invalid address", + input: &banktypes.MsgSend{ + FromAddress: "", + ToAddress: addrs[1].String(), + Amount: origCoins, + }, + expErr: true, + expErrMsg: "empty address string is not allowed", + }, + { + name: "invalid to address: empty address string is not allowed: invalid address", + input: &banktypes.MsgSend{ + FromAddress: addrs[0].String(), + ToAddress: "", + Amount: origCoins, + }, + expErr: true, + expErrMsg: "empty address string is not allowed", + }, + { + name: "all good", + input: &banktypes.MsgSend{ + FromAddress: addrs[0].String(), + ToAddress: addrs[1].String(), + Amount: origCoins, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + + if tc.input.Amount.IsAllPositive() && tc.input.FromAddress != "" { + fromAddr, err := input.AccountKeeper.AddressCodec().StringToBytes(tc.input.FromAddress) + require.NoError(t, err) + input.Faucet.Fund(ctx, fromAddr, tc.input.Amount...) + } + + _, err := bankkeeper.NewMsgServerImpl(input.BankKeeper).Send(ctx, tc.input) + if tc.expErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErrMsg) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgSetSendEnabled(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + testCases := []struct { + name string + req *banktypes.MsgSetSendEnabled + isExpErr bool + errMsg string + }{ + { + name: "all good", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("atom1", true), + }, + []string{}, + ), + }, + { + name: "all good with two denoms", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("atom1", true), + banktypes.NewSendEnabled("atom2", true), + }, + []string{"defcoinc", "defcoind"}, + ), + }, + { + name: "duplicate denoms", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("atom", true), + banktypes.NewSendEnabled("atom", true), + }, + []string{}, + ), + isExpErr: true, + errMsg: `duplicate denom entries found for "atom": invalid request`, + }, + { + name: "bad first denom name, (invalid send enabled denom present in list)", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("not a denom", true), + banktypes.NewSendEnabled("somecoin", true), + }, + []string{}, + ), + isExpErr: true, + errMsg: `invalid SendEnabled denom "not a denom": invalid denom: not a denom: invalid request`, + }, + { + name: "bad second denom name, (invalid send enabled denom present in list)", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("somecoin", true), + banktypes.NewSendEnabled("not a denom", true), + }, + []string{}, + ), + isExpErr: true, + errMsg: `invalid SendEnabled denom "not a denom": invalid denom: not a denom: invalid request`, + }, + { + name: "invalid UseDefaultFor denom", + req: banktypes.NewMsgSetSendEnabled( + govAcc.GetAddress().String(), + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("atom", true), + }, + []string{"not a denom"}, + ), + isExpErr: true, + errMsg: `invalid UseDefaultFor denom "not a denom": invalid denom: not a denom: invalid request`, + }, + { + name: "invalid authority", + req: banktypes.NewMsgSetSendEnabled( + "invalid", + []*banktypes.SendEnabled{ + banktypes.NewSendEnabled("atom", true), + }, + []string{}, + ), + isExpErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := bankkeeper.NewMsgServerImpl(input.BankKeeper).SetSendEnabled(ctx, tc.req) + + if tc.isExpErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go new file mode 100644 index 0000000..8b2df6d --- /dev/null +++ b/x/bank/keeper/send.go @@ -0,0 +1,335 @@ +package keeper + +import ( + "context" + "fmt" + + "cosmossdk.io/core/store" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + cosmosbank "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var _ cosmosbank.SendKeeper = (*MoveSendKeeper)(nil) + +// MoveSendKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the SendKeeper interface. +type MoveSendKeeper struct { + MoveViewKeeper + + cdc codec.BinaryCodec + ak types.AccountKeeper + storeService store.KVStoreService + + // list of addresses that are restricted from receiving transactions + blockedAddrs map[string]bool + + // the address capable of executing a MsgUpdateParams message. Typically, this + // should be the x/gov module account. + authority string + + sendRestriction *sendRestriction +} + +func NewMoveSendKeeper( + cdc codec.BinaryCodec, + storeService store.KVStoreService, + ak types.AccountKeeper, + ek evmtypes.IERC20Keeper, + blockedAddrs map[string]bool, + authority string, +) MoveSendKeeper { + if _, err := ak.AddressCodec().StringToBytes(authority); err != nil { + panic(fmt.Errorf("invalid bank authority address: %w", err)) + } + + return MoveSendKeeper{ + MoveViewKeeper: NewMoveViewKeeper(cdc, storeService, ak, ek), + cdc: cdc, + ak: ak, + storeService: storeService, + blockedAddrs: blockedAddrs, + authority: authority, + sendRestriction: newSendRestriction(), + } +} + +// AppendSendRestriction adds the provided SendRestrictionFn to run after previously provided restrictions. +func (k MoveSendKeeper) AppendSendRestriction(restriction types.SendRestrictionFn) { + k.sendRestriction.append(restriction) +} + +// PrependSendRestriction adds the provided SendRestrictionFn to run before previously provided restrictions. +func (k MoveSendKeeper) PrependSendRestriction(restriction types.SendRestrictionFn) { + k.sendRestriction.prepend(restriction) +} + +// ClearSendRestriction removes the send restriction (if there is one). +func (k MoveSendKeeper) ClearSendRestriction() { + k.sendRestriction.clear() +} + +// GetAuthority returns the x/bank module's authority. +func (k MoveSendKeeper) GetAuthority() string { + return k.authority +} + +// GetParams returns the total set of bank parameters. +func (k MoveSendKeeper) GetParams(ctx context.Context) (params types.Params) { + p, _ := k.Params.Get(ctx) + return p +} + +// SetParams sets the total set of bank parameters. +// +// Note: params.SendEnabled is deprecated but it should be here regardless. +// +//nolint:staticcheck +func (k MoveSendKeeper) SetParams(ctx context.Context, params types.Params) error { + // Normally SendEnabled is deprecated but we still support it for backwards + // compatibility. Using params.Validate() would fail due to the SendEnabled + // deprecation. + if len(params.SendEnabled) > 0 { //nolint:staticcheck // SA1019: params.SendEnabled is deprecated + k.SetAllSendEnabled(ctx, params.SendEnabled) //nolint:staticcheck // SA1019: params.SendEnabled is deprecated + + // override params without SendEnabled + params = types.NewParams(params.DefaultSendEnabled) + } + return k.Params.Set(ctx, params) +} + +// InputOutputCoins performs multi-send functionality. It accepts a series of +// inputs that correspond to a series of outputs. It returns an error if the +// inputs and outputs don't lineup or if any single transfer of tokens fails. +func (k MoveSendKeeper) InputOutputCoins(ctx context.Context, inputs types.Input, outputs []types.Output) error { + return sdkerrors.ErrNotSupported +} + +// SendCoins transfers amt coins from a sending account to a receiving account. +// An error is returned upon failure. +func (k MoveSendKeeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { + toAddr, err := k.sendRestriction.apply(ctx, fromAddr, toAddr, amt) + if err != nil { + return err + } + + err = k.ek.SendCoins(ctx, fromAddr, toAddr, amt) + if err != nil { + return err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + // emit coin spent event + sdkCtx.EventManager().EmitEvent( + types.NewCoinSpentEvent(fromAddr, amt), + ) + + // emit coin received event + sdkCtx.EventManager().EmitEvent( + types.NewCoinReceivedEvent(toAddr, amt), + ) + + // Create account if recipient does not exist. + // + // NOTE: This should ultimately be removed in favor a more flexible approach + // such as delegated fee messages. + accExists := k.ak.HasAccount(ctx, toAddr) + if !accExists { + defer telemetry.IncrCounter(1, "new", "account") + k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, toAddr)) + } + + sdkCtx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeTransfer, + sdk.NewAttribute(types.AttributeKeyRecipient, toAddr.String()), + sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amt.String()), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()), + ), + }) + + return nil +} + +// initBalances sets the balance (multiple coins) for an account by address. +// An error is returned upon failure. +func (k MoveSendKeeper) initBalances(ctx context.Context, addr sdk.AccAddress, balances sdk.Coins) error { + return k.ek.MintCoins(ctx, addr, balances) +} + +// IsSendEnabledCoins checks the coins provided and returns an ErrSendDisabled +// if any of the coins are not configured for sending. Returns nil if sending is +// enabled for all provided coins. +func (k MoveSendKeeper) IsSendEnabledCoins(ctx context.Context, coins ...sdk.Coin) error { + if len(coins) == 0 { + return nil + } + + defaultVal := k.GetParams(ctx).DefaultSendEnabled + + for _, coin := range coins { + if !k.getSendEnabledOrDefault(ctx, coin.Denom, defaultVal) { + return types.ErrSendDisabled.Wrapf("%s transfers are currently disabled", coin.Denom) + } + } + + return nil +} + +// IsSendEnabledCoin returns the current SendEnabled status of the provided coin's denom +func (k MoveSendKeeper) IsSendEnabledCoin(ctx context.Context, coin sdk.Coin) bool { + return k.IsSendEnabledDenom(ctx, coin.Denom) +} + +// BlockedAddr checks if a given address is restricted from +// receiving funds. +func (k MoveSendKeeper) BlockedAddr(addr sdk.AccAddress) bool { + return k.blockedAddrs[addr.String()] +} + +// GetBlockedAddresses returns the full list of addresses restricted from receiving funds. +func (k MoveSendKeeper) GetBlockedAddresses() map[string]bool { + return k.blockedAddrs +} + +// IsSendEnabledDenom returns the current SendEnabled status of the provided denom. +func (k MoveSendKeeper) IsSendEnabledDenom(ctx context.Context, denom string) bool { + return k.getSendEnabledOrDefault(ctx, denom, k.GetParams(ctx).DefaultSendEnabled) +} + +// GetSendEnabledEntry gets a SendEnabled entry for the given denom. +// The second return argument is true iff a specific entry exists for the given denom. +func (k MoveSendKeeper) GetSendEnabledEntry(ctx context.Context, denom string) (types.SendEnabled, bool) { + sendEnabled, found := k.getSendEnabled(ctx, denom) + if !found { + return types.SendEnabled{}, false + } + + return types.SendEnabled{Denom: denom, Enabled: sendEnabled}, true +} + +// SetSendEnabled sets the SendEnabled flag for a denom to the provided value. +func (k MoveSendKeeper) SetSendEnabled(ctx context.Context, denom string, value bool) { + _ = k.SendEnabled.Set(ctx, denom, value) +} + +// SetAllSendEnabled sets all the provided SendEnabled entries in the bank store. +func (k MoveSendKeeper) SetAllSendEnabled(ctx context.Context, entries []*types.SendEnabled) { + for _, entry := range entries { + _ = k.SendEnabled.Set(ctx, entry.Denom, entry.Enabled) + } +} + +// DeleteSendEnabled deletes the SendEnabled flags for one or more denoms. +// If a denom is provided that doesn't have a SendEnabled entry, it is ignored. +func (k MoveSendKeeper) DeleteSendEnabled(ctx context.Context, denoms ...string) { + for _, denom := range denoms { + _ = k.SendEnabled.Remove(ctx, denom) + } +} + +// IterateSendEnabledEntries iterates over all the SendEnabled entries. +func (k MoveSendKeeper) IterateSendEnabledEntries(ctx context.Context, cb func(denom string, sendEnabled bool) bool) { + err := k.SendEnabled.Walk(ctx, nil, func(key string, value bool) (stop bool, err error) { + return cb(key, value), nil + }) + if err != nil { + panic(err) + } +} + +// GetAllSendEnabledEntries gets all the SendEnabled entries that are stored. +// Any denominations not returned use the default value (set in Params). +func (k MoveSendKeeper) GetAllSendEnabledEntries(ctx context.Context) []types.SendEnabled { + var rv []types.SendEnabled + k.IterateSendEnabledEntries(ctx, func(denom string, sendEnabled bool) bool { + rv = append(rv, types.SendEnabled{Denom: denom, Enabled: sendEnabled}) + return false + }) + + return rv +} + +// getSendEnabled returns whether send is enabled and whether that flag was set +// for a denom. +// +// Example usage: +// +// store := ctx.KVStore(k.storeKey) +// sendEnabled, found := getSendEnabled(store, "atom") +// if !found { +// sendEnabled = DefaultSendEnabled +// } +func (k MoveSendKeeper) getSendEnabled(ctx context.Context, denom string) (bool, bool) { + has, err := k.SendEnabled.Has(ctx, denom) + if err != nil || !has { + return false, false + } + + v, err := k.SendEnabled.Get(ctx, denom) + if err != nil { + return false, false + } + + return v, true +} + +// getSendEnabledOrDefault gets the SendEnabled value for a denom. If it's not +// in the store, this will return defaultVal. +func (k MoveSendKeeper) getSendEnabledOrDefault(ctx context.Context, denom string, defaultVal bool) bool { + sendEnabled, found := k.getSendEnabled(ctx, denom) + if found { + return sendEnabled + } + + return defaultVal +} + +// sendRestriction is a struct that houses a SendRestrictionFn. +// It exists so that the SendRestrictionFn can be updated in the SendKeeper without needing to have a pointer receiver. +type sendRestriction struct { + fn types.SendRestrictionFn +} + +// newSendRestriction creates a new sendRestriction with nil send restriction. +func newSendRestriction() *sendRestriction { + return &sendRestriction{ + fn: nil, + } +} + +// append adds the provided restriction to this, to be run after the existing function. +func (r *sendRestriction) append(restriction types.SendRestrictionFn) { + r.fn = r.fn.Then(restriction) +} + +// prepend adds the provided restriction to this, to be run before the existing function. +func (r *sendRestriction) prepend(restriction types.SendRestrictionFn) { + r.fn = restriction.Then(r.fn) +} + +// clear removes the send restriction (sets it to nil). +func (r *sendRestriction) clear() { + r.fn = nil +} + +var _ types.SendRestrictionFn = (*sendRestriction)(nil).apply + +// apply applies the send restriction if there is one. If not, it's a no-op. +func (r *sendRestriction) apply(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) (sdk.AccAddress, error) { + if r == nil || r.fn == nil { + return toAddr, nil + } + return r.fn(ctx, fromAddr, toAddr, amt) +} diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go new file mode 100644 index 0000000..d462d57 --- /dev/null +++ b/x/bank/keeper/view.go @@ -0,0 +1,197 @@ +package keeper + +import ( + "context" + "fmt" + + "cosmossdk.io/collections" + "cosmossdk.io/core/store" + "cosmossdk.io/log" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + cosmoskeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +var _ cosmoskeeper.ViewKeeper = (*MoveViewKeeper)(nil) + +// MoveViewKeeper implements a read only keeper implementation of ViewKeeper. +type MoveViewKeeper struct { + cdc codec.BinaryCodec + storeService store.KVStoreService + ak types.AccountKeeper + ek evmtypes.IERC20Keeper + + Schema collections.Schema + DenomMetadata collections.Map[string, types.Metadata] + SendEnabled collections.Map[string, bool] + Params collections.Item[types.Params] +} + +// NewMoveViewKeeper returns a new MoveViewKeeper. +func NewMoveViewKeeper( + cdc codec.BinaryCodec, + storeService store.KVStoreService, + ak types.AccountKeeper, + ek evmtypes.IERC20Keeper, +) MoveViewKeeper { + sb := collections.NewSchemaBuilder(storeService) + k := MoveViewKeeper{ + cdc: cdc, + storeService: storeService, + ak: ak, + ek: ek, + + DenomMetadata: collections.NewMap(sb, types.DenomMetadataPrefix, "denom_metadata", collections.StringKey, codec.CollValue[types.Metadata](cdc)), + SendEnabled: collections.NewMap(sb, types.SendEnabledPrefix, "send_enabled", collections.StringKey, codec.BoolValue), // NOTE: we use a bool value which uses protobuf to retain state backwards compat + Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + } + + schema, err := sb.Build() + if err != nil { + panic(err) + } + k.Schema = schema + return k +} + +// Logger returns a module-specific logger. +func (k MoveViewKeeper) Logger(ctx context.Context) log.Logger { + sdkCtx := sdk.UnwrapSDKContext(ctx) + return sdkCtx.Logger().With("module", "x/"+types.ModuleName) +} + +// HasBalance returns whether or not an account has at least amt balance. +func (k MoveViewKeeper) HasBalance(ctx context.Context, addr sdk.AccAddress, amt sdk.Coin) bool { + return k.GetBalance(ctx, addr, amt.Denom).IsGTE(amt) +} + +// GetAllBalances returns all the account balances for the given account address. +func (k MoveViewKeeper) GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + balances := sdk.NewCoins() + k.IterateAccountBalances(ctx, addr, func(balance sdk.Coin) bool { + balances = balances.Add(balance) + return false + }) + + return balances.Sort() +} + +// GetAccountsBalances returns all the accounts balances from the store. +func (k MoveViewKeeper) GetAccountsBalances(ctx context.Context) []types.Balance { + balances := make([]types.Balance, 0) + mapAddressToBalancesIdx := make(map[string]int) + + k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool { + idx, ok := mapAddressToBalancesIdx[addr.String()] + if ok { + // address is already on the set of accounts balances + balances[idx].Coins = balances[idx].Coins.Add(balance) + balances[idx].Coins.Sort() + return false + } + + accountBalance := types.Balance{ + Address: addr.String(), + Coins: sdk.NewCoins(balance), + } + balances = append(balances, accountBalance) + mapAddressToBalancesIdx[addr.String()] = len(balances) - 1 + return false + }) + + return balances +} + +// GetBalance returns the balance of a specific denomination for a given account +// by address. +func (k MoveViewKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin { + balance, err := k.ek.GetBalance(ctx, addr, denom) + if err != nil { + panic(err) + } + + return sdk.NewCoin(denom, balance) +} + +// IterateAccountBalances iterates over the balances of a single account and +// provides the token balance to a callback. If true is returned from the +// callback, iteration is halted. +func (k MoveViewKeeper) IterateAccountBalances(ctx context.Context, addr sdk.AccAddress, cb func(sdk.Coin) bool) { + err := k.ek.IterateAccountBalances(ctx, addr, func(c sdk.Coin) (bool, error) { + return cb(c), nil + }) + if err != nil { + panic(err) + } +} + +// IterateAllBalances iterates over all the balances of all accounts and +// denominations that are provided to a callback. If true is returned from the +// callback, iteration is halted. +func (k MoveViewKeeper) IterateAllBalances(ctx context.Context, cb func(sdk.AccAddress, sdk.Coin) bool) { + k.ak.IterateAccounts(ctx, func(account sdk.AccountI) bool { + addr := account.GetAddress() + err := k.ek.IterateAccountBalances(ctx, addr, func(coin sdk.Coin) (bool, error) { + return cb(addr, coin), nil + }) + if err != nil { + panic(err) + } + + return false + }) +} + +// LockedCoins returns all the coins that are not spendable (i.e. locked) for an +// account by address. For standard accounts, the result will always be no coins. +func (k MoveViewKeeper) LockedCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + return sdk.NewCoins() +} + +// SpendableCoins returns the total balances of spendable coins for an account +// by address. If the account has no spendable coins, an empty Coins slice is +// returned. +func (k MoveViewKeeper) SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + spendable, _ := k.spendableCoins(ctx, addr) + return spendable +} + +// SpendableCoin returns the balance of specific denomination of spendable coins +// for an account by address. If the account has no spendable coin, a zero Coin +// is returned. +func (k MoveViewKeeper) SpendableCoin(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin { + balance := k.GetBalance(ctx, addr, denom) + locked := k.LockedCoins(ctx, addr) + return balance.SubAmount(locked.AmountOf(denom)) +} + +// spendableCoins returns the coins the given address can spend alongside the total amount of coins it holds. +// It exists for gas efficiency, in order to avoid to have to get balance multiple times. +func (k MoveViewKeeper) spendableCoins(ctx context.Context, addr sdk.AccAddress) (spendable, total sdk.Coins) { + total = k.GetAllBalances(ctx, addr) + locked := k.LockedCoins(ctx, addr) + + spendable, hasNeg := total.SafeSub(locked...) + if hasNeg { + spendable = sdk.NewCoins() + return + } + + return +} + +// ValidateBalance validates all balances for a given account address returning +// an error if any balance is invalid. +// +// CONTRACT: ValidateBalance should only be called upon genesis state. +func (k MoveViewKeeper) ValidateBalance(ctx context.Context, addr sdk.AccAddress) error { + balances := k.GetAllBalances(ctx, addr) + if !balances.IsValid() { + return fmt.Errorf("account balance of %s is invalid", balances) + } + + return nil +} diff --git a/x/bank/module.go b/x/bank/module.go new file mode 100644 index 0000000..0ae9584 --- /dev/null +++ b/x/bank/module.go @@ -0,0 +1,144 @@ +package bank + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "cosmossdk.io/core/appmodule" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/bank/client/cli" + "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/initia-labs/minievm/x/bank/keeper" + customtypes "github.com/initia-labs/minievm/x/bank/types" +) + +const ConsensusVersion = 1 + +var ( + _ module.AppModuleBasic = AppModule{} + _ module.HasGenesis = AppModule{} + _ module.HasServices = AppModule{} + _ module.HasInvariants = AppModule{} + + _ appmodule.AppModule = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the bank module. +type AppModuleBasic struct { + cdc codec.Codec +} + +func NewAppModuleBasic(cdc codec.Codec) AppModuleBasic { + return AppModuleBasic{cdc} +} + +// Name returns the bank module's name. +func (AppModuleBasic) Name() string { return types.ModuleName } + +// RegisterLegacyAminoCodec registers the bank module's types on the LegacyAmino codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) + customtypes.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis returns default genesis state as raw bytes for the bank +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the bank module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return data.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the bank module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// GetTxCmd returns the root tx command for the bank module. +func (b AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd(b.cdc.InterfaceRegistry().SigningContext().AddressCodec()) +} + +// RegisterInterfaces registers interfaces and implementations of the bank module. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + customtypes.RegisterInterfaces(registry) + types.RegisterInterfaces(registry) +} + +// AppModule implements an application module for the bank module. +type AppModule struct { + AppModuleBasic + + keeper keeper.BaseKeeper + accountKeeper types.AccountKeeper +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + customtypes.RegisterMsgServer(cfg.MsgServer(), keeper.NewCustomMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// NewAppModule creates a new AppModule object +func NewAppModule(cdc codec.Codec, keeper keeper.BaseKeeper, accountKeeper types.AccountKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + accountKeeper: accountKeeper, + } +} + +// Name returns the bank module's name. +func (AppModule) Name() string { return types.ModuleName } + +// RegisterInvariants registers the bank module invariants. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// InitGenesis performs genesis initialization for the bank module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) { + start := time.Now() + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + telemetry.MeasureSince(start, "InitGenesis", "crisis", "unmarshal") + + am.keeper.InitGenesis(ctx, &genesisState) +} + +// ExportGenesis returns the exported genesis state as raw bytes for the bank +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } + +// IsAppModule implements the appmodule.AppModule interface. +func (am AppModule) IsAppModule() {} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (am AppModule) IsOnePerModuleType() {} diff --git a/x/bank/types/codec.go b/x/bank/types/codec.go new file mode 100644 index 0000000..f9afe26 --- /dev/null +++ b/x/bank/types/codec.go @@ -0,0 +1,26 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// RegisterLegacyAminoCodec registers the necessary x/bank interfaces +// and concrete types on the provided LegacyAmino codec. These types are used +// for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + legacy.RegisterAminoMsg(cdc, &MsgSetDenomMetadata{}, "bank/MsgSetDenomMetadata") +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgSetDenomMetadata{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/bank/types/tx.pb.go b/x/bank/types/tx.pb.go new file mode 100644 index 0000000..11e7ae1 --- /dev/null +++ b/x/bank/types/tx.pb.go @@ -0,0 +1,599 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: minievm/bank/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types "github.com/cosmos/cosmos-sdk/x/bank/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgSetDenomMetadata is the Msg/UpdateParams request type. +type MsgSetDenomMetadata struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // metadata defines the x/bank denom metadata to update. + Metadata types.Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata"` +} + +func (m *MsgSetDenomMetadata) Reset() { *m = MsgSetDenomMetadata{} } +func (m *MsgSetDenomMetadata) String() string { return proto.CompactTextString(m) } +func (*MsgSetDenomMetadata) ProtoMessage() {} +func (*MsgSetDenomMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_e27d47e6a0b6bcf0, []int{0} +} +func (m *MsgSetDenomMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetDenomMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetDenomMetadata.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 *MsgSetDenomMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetDenomMetadata.Merge(m, src) +} +func (m *MsgSetDenomMetadata) XXX_Size() int { + return m.Size() +} +func (m *MsgSetDenomMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetDenomMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetDenomMetadata proto.InternalMessageInfo + +func (m *MsgSetDenomMetadata) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgSetDenomMetadata) GetMetadata() types.Metadata { + if m != nil { + return m.Metadata + } + return types.Metadata{} +} + +// MsgSetDenomMetadataResponse defines the response structure for executing a +// MsgSetDenomMetadata message. +type MsgSetDenomMetadataResponse struct { +} + +func (m *MsgSetDenomMetadataResponse) Reset() { *m = MsgSetDenomMetadataResponse{} } +func (m *MsgSetDenomMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetDenomMetadataResponse) ProtoMessage() {} +func (*MsgSetDenomMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_e27d47e6a0b6bcf0, []int{1} +} +func (m *MsgSetDenomMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetDenomMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetDenomMetadataResponse.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 *MsgSetDenomMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetDenomMetadataResponse.Merge(m, src) +} +func (m *MsgSetDenomMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetDenomMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetDenomMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetDenomMetadataResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgSetDenomMetadata)(nil), "minievm.bank.v1.MsgSetDenomMetadata") + proto.RegisterType((*MsgSetDenomMetadataResponse)(nil), "minievm.bank.v1.MsgSetDenomMetadataResponse") +} + +func init() { proto.RegisterFile("minievm/bank/v1/tx.proto", fileDescriptor_e27d47e6a0b6bcf0) } + +var fileDescriptor_e27d47e6a0b6bcf0 = []byte{ + // 370 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xc8, 0xcd, 0xcc, 0xcb, + 0x4c, 0x2d, 0xcb, 0xd5, 0x4f, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, + 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, 0xca, 0xe8, 0x81, 0x64, 0xf4, 0xca, 0x0c, 0xa5, 0x04, + 0x13, 0x73, 0x33, 0xf3, 0xf2, 0xf5, 0xc1, 0x24, 0x44, 0x8d, 0x94, 0x5c, 0x72, 0x7e, 0x71, 0x6e, + 0x7e, 0x31, 0x4c, 0x73, 0x52, 0x6a, 0x49, 0xa2, 0x21, 0x98, 0x03, 0x95, 0x17, 0x87, 0xca, 0xe7, + 0x16, 0xa7, 0x83, 0xcc, 0xce, 0x2d, 0x4e, 0x87, 0x4a, 0x48, 0x42, 0x24, 0xe2, 0xc1, 0x3c, 0x7d, + 0x08, 0x07, 0x2a, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x11, 0x07, 0xb1, 0x20, 0xa2, 0x4a, 0x07, + 0x18, 0xb9, 0x84, 0x7d, 0x8b, 0xd3, 0x83, 0x53, 0x4b, 0x5c, 0x52, 0xf3, 0xf2, 0x73, 0x7d, 0x53, + 0x4b, 0x12, 0x53, 0x12, 0x4b, 0x12, 0x85, 0xcc, 0xb8, 0x38, 0x13, 0x4b, 0x4b, 0x32, 0xf2, 0x8b, + 0x32, 0x4b, 0x2a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x9d, 0x24, 0x2e, 0x6d, 0xd1, 0x15, 0x81, + 0x1a, 0xe9, 0x98, 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, + 0x50, 0x2a, 0xe4, 0xc2, 0xc5, 0x91, 0x0b, 0x35, 0x43, 0x82, 0x49, 0x81, 0x51, 0x83, 0xdb, 0x48, + 0x56, 0x0f, 0xaa, 0x07, 0xea, 0x5f, 0xb0, 0x67, 0xf4, 0x60, 0x16, 0x39, 0x71, 0x9e, 0xb8, 0x27, + 0xcf, 0xb0, 0xe2, 0xf9, 0x06, 0x2d, 0xc6, 0x20, 0xb8, 0x4e, 0x2b, 0xed, 0xa6, 0xe7, 0x1b, 0xb4, + 0x10, 0xa6, 0x76, 0x3d, 0xdf, 0xa0, 0x25, 0x01, 0x0e, 0x0b, 0x2c, 0x4e, 0x55, 0x92, 0xe5, 0x92, + 0xc6, 0x22, 0x1c, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x6a, 0x54, 0xc2, 0xc5, 0xec, 0x5b, + 0x9c, 0x2e, 0x94, 0xc6, 0x25, 0x80, 0xe1, 0x49, 0x15, 0x3d, 0xb4, 0xb8, 0xd0, 0xc3, 0x62, 0x90, + 0x94, 0x0e, 0x31, 0xaa, 0x60, 0xd6, 0x49, 0xb1, 0x36, 0x80, 0xfc, 0xe2, 0xe4, 0xb9, 0xe2, 0x91, + 0x1c, 0xc3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, + 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa7, 0x67, 0x96, + 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x67, 0xe6, 0x65, 0x96, 0x64, 0x26, 0xea, 0xe6, + 0x24, 0x26, 0x15, 0xeb, 0xc3, 0x12, 0x4d, 0x05, 0x24, 0xe6, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, + 0xd8, 0xc0, 0x31, 0x65, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x64, 0x80, 0xad, 0xd4, 0x53, 0x02, + 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // SetDenomMetadata defines a governance operation for updating the x/bank + // denom metadata. The authority is defined in the keeper. + SetDenomMetadata(ctx context.Context, in *MsgSetDenomMetadata, opts ...grpc.CallOption) (*MsgSetDenomMetadataResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) SetDenomMetadata(ctx context.Context, in *MsgSetDenomMetadata, opts ...grpc.CallOption) (*MsgSetDenomMetadataResponse, error) { + out := new(MsgSetDenomMetadataResponse) + err := c.cc.Invoke(ctx, "/minievm.bank.v1.Msg/SetDenomMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // SetDenomMetadata defines a governance operation for updating the x/bank + // denom metadata. The authority is defined in the keeper. + SetDenomMetadata(context.Context, *MsgSetDenomMetadata) (*MsgSetDenomMetadataResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) SetDenomMetadata(ctx context.Context, req *MsgSetDenomMetadata) (*MsgSetDenomMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetDenomMetadata not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_SetDenomMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetDenomMetadata) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetDenomMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/minievm.bank.v1.Msg/SetDenomMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetDenomMetadata(ctx, req.(*MsgSetDenomMetadata)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "minievm.bank.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SetDenomMetadata", + Handler: _Msg_SetDenomMetadata_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "minievm/bank/v1/tx.proto", +} + +func (m *MsgSetDenomMetadata) 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 *MsgSetDenomMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetDenomMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSetDenomMetadataResponse) 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 *MsgSetDenomMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgSetDenomMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Metadata.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgSetDenomMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgSetDenomMetadata) 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 ErrIntOverflowTx + } + 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: MsgSetDenomMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetDenomMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetDenomMetadataResponse) 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 ErrIntOverflowTx + } + 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: MsgSetDenomMetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetDenomMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/evm/contracts/counter/Counter.go b/x/evm/contracts/counter/Counter.go index bc70b16..1f9a172 100644 --- a/x/evm/contracts/counter/Counter.go +++ b/x/evm/contracts/counter/Counter.go @@ -32,7 +32,7 @@ var ( // CounterMetaData contains all meta data concerning the Counter contract. var CounterMetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCount\",\"type\":\"uint256\"}],\"name\":\"increased\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"increase\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561000f575f80fd5b506101f98061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806306661abd14610038578063e8927fbc14610056575b5f80fd5b610040610060565b60405161004d91906100dc565b60405180910390f35b61005e610065565b005b5f5481565b5f8081548092919061007690610122565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f546100aa9190610169565b5f546040516100ba92919061019c565b60405180910390a1565b5f819050919050565b6100d6816100c4565b82525050565b5f6020820190506100ef5f8301846100cd565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61012c826100c4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361015e5761015d6100f5565b5b600182019050919050565b5f610173826100c4565b915061017e836100c4565b9250828203905081811115610196576101956100f5565b5b92915050565b5f6040820190506101af5f8301856100cd565b6101bc60208301846100cd565b939250505056fea26469706673582212203c122e21a4aef376978d3db66ecf702eb299495a2803fa01bc7f851828ebdd7f64736f6c63430008180033", + Bin: "0x608060405234801561000f575f80fd5b506101f98061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806306661abd14610038578063e8927fbc14610056575b5f80fd5b610040610060565b60405161004d91906100dc565b60405180910390f35b61005e610065565b005b5f5481565b5f8081548092919061007690610122565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f546100aa9190610169565b5f546040516100ba92919061019c565b60405180910390a1565b5f819050919050565b6100d6816100c4565b82525050565b5f6020820190506100ef5f8301846100cd565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61012c826100c4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361015e5761015d6100f5565b5b600182019050919050565b5f610173826100c4565b915061017e836100c4565b9250828203905081811115610196576101956100f5565b5b92915050565b5f6040820190506101af5f8301856100cd565b6101bc60208301846100cd565b939250505056fea26469706673582212205af05190048c7917b0ee5ebf1492cb1d07ff48b691d3fabc63d863923408e7a864736f6c63430008180033", } // CounterABI is the input ABI used to generate the binding from. diff --git a/x/evm/contracts/counter/Counter.sol b/x/evm/contracts/counter/Counter.sol index 87ea59d..8a5e601 100644 --- a/x/evm/contracts/counter/Counter.sol +++ b/x/evm/contracts/counter/Counter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.24; contract Counter { uint256 public count; diff --git a/x/evm/contracts/double_counter/DoubleCounter.go b/x/evm/contracts/double_counter/DoubleCounter.go deleted file mode 100644 index 123de97..0000000 --- a/x/evm/contracts/double_counter/DoubleCounter.go +++ /dev/null @@ -1,255 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package double_counter - -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 -) - -// DoubleCounterMetaData contains all meta data concerning the DoubleCounter contract. -var DoubleCounterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"increase\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561000f575f80fd5b506101468061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806306661abd14610038578063e8927fbc14610056575b5f80fd5b610040610060565b60405161004d9190610097565b60405180910390f35b61005e610065565b005b5f5481565b60025f8082825461007691906100dd565b92505081905550565b5f819050919050565b6100918161007f565b82525050565b5f6020820190506100aa5f830184610088565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6100e78261007f565b91506100f28361007f565b925082820190508082111561010a576101096100b0565b5b9291505056fea26469706673582212207f99c62aef3d87ded350e2034fe1971ea63985a0b8ab02c2d1a51417f74f660864736f6c63430008180033", -} - -// DoubleCounterABI is the input ABI used to generate the binding from. -// Deprecated: Use DoubleCounterMetaData.ABI instead. -var DoubleCounterABI = DoubleCounterMetaData.ABI - -// DoubleCounterBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use DoubleCounterMetaData.Bin instead. -var DoubleCounterBin = DoubleCounterMetaData.Bin - -// DeployDoubleCounter deploys a new Ethereum contract, binding an instance of DoubleCounter to it. -func DeployDoubleCounter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DoubleCounter, error) { - parsed, err := DoubleCounterMetaData.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(DoubleCounterBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &DoubleCounter{DoubleCounterCaller: DoubleCounterCaller{contract: contract}, DoubleCounterTransactor: DoubleCounterTransactor{contract: contract}, DoubleCounterFilterer: DoubleCounterFilterer{contract: contract}}, nil -} - -// DoubleCounter is an auto generated Go binding around an Ethereum contract. -type DoubleCounter struct { - DoubleCounterCaller // Read-only binding to the contract - DoubleCounterTransactor // Write-only binding to the contract - DoubleCounterFilterer // Log filterer for contract events -} - -// DoubleCounterCaller is an auto generated read-only Go binding around an Ethereum contract. -type DoubleCounterCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DoubleCounterTransactor is an auto generated write-only Go binding around an Ethereum contract. -type DoubleCounterTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DoubleCounterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type DoubleCounterFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DoubleCounterSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type DoubleCounterSession struct { - Contract *DoubleCounter // 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 -} - -// DoubleCounterCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type DoubleCounterCallerSession struct { - Contract *DoubleCounterCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// DoubleCounterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type DoubleCounterTransactorSession struct { - Contract *DoubleCounterTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// DoubleCounterRaw is an auto generated low-level Go binding around an Ethereum contract. -type DoubleCounterRaw struct { - Contract *DoubleCounter // Generic contract binding to access the raw methods on -} - -// DoubleCounterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type DoubleCounterCallerRaw struct { - Contract *DoubleCounterCaller // Generic read-only contract binding to access the raw methods on -} - -// DoubleCounterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type DoubleCounterTransactorRaw struct { - Contract *DoubleCounterTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewDoubleCounter creates a new instance of DoubleCounter, bound to a specific deployed contract. -func NewDoubleCounter(address common.Address, backend bind.ContractBackend) (*DoubleCounter, error) { - contract, err := bindDoubleCounter(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &DoubleCounter{DoubleCounterCaller: DoubleCounterCaller{contract: contract}, DoubleCounterTransactor: DoubleCounterTransactor{contract: contract}, DoubleCounterFilterer: DoubleCounterFilterer{contract: contract}}, nil -} - -// NewDoubleCounterCaller creates a new read-only instance of DoubleCounter, bound to a specific deployed contract. -func NewDoubleCounterCaller(address common.Address, caller bind.ContractCaller) (*DoubleCounterCaller, error) { - contract, err := bindDoubleCounter(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &DoubleCounterCaller{contract: contract}, nil -} - -// NewDoubleCounterTransactor creates a new write-only instance of DoubleCounter, bound to a specific deployed contract. -func NewDoubleCounterTransactor(address common.Address, transactor bind.ContractTransactor) (*DoubleCounterTransactor, error) { - contract, err := bindDoubleCounter(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &DoubleCounterTransactor{contract: contract}, nil -} - -// NewDoubleCounterFilterer creates a new log filterer instance of DoubleCounter, bound to a specific deployed contract. -func NewDoubleCounterFilterer(address common.Address, filterer bind.ContractFilterer) (*DoubleCounterFilterer, error) { - contract, err := bindDoubleCounter(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &DoubleCounterFilterer{contract: contract}, nil -} - -// bindDoubleCounter binds a generic wrapper to an already deployed contract. -func bindDoubleCounter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := DoubleCounterMetaData.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 (_DoubleCounter *DoubleCounterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DoubleCounter.Contract.DoubleCounterCaller.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 (_DoubleCounter *DoubleCounterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DoubleCounter.Contract.DoubleCounterTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DoubleCounter *DoubleCounterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DoubleCounter.Contract.DoubleCounterTransactor.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 (_DoubleCounter *DoubleCounterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DoubleCounter.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 (_DoubleCounter *DoubleCounterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DoubleCounter.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DoubleCounter *DoubleCounterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DoubleCounter.Contract.contract.Transact(opts, method, params...) -} - -// Count is a free data retrieval call binding the contract method 0x06661abd. -// -// Solidity: function count() view returns(uint256) -func (_DoubleCounter *DoubleCounterCaller) Count(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _DoubleCounter.contract.Call(opts, &out, "count") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Count is a free data retrieval call binding the contract method 0x06661abd. -// -// Solidity: function count() view returns(uint256) -func (_DoubleCounter *DoubleCounterSession) Count() (*big.Int, error) { - return _DoubleCounter.Contract.Count(&_DoubleCounter.CallOpts) -} - -// Count is a free data retrieval call binding the contract method 0x06661abd. -// -// Solidity: function count() view returns(uint256) -func (_DoubleCounter *DoubleCounterCallerSession) Count() (*big.Int, error) { - return _DoubleCounter.Contract.Count(&_DoubleCounter.CallOpts) -} - -// Increase is a paid mutator transaction binding the contract method 0xe8927fbc. -// -// Solidity: function increase() returns() -func (_DoubleCounter *DoubleCounterTransactor) Increase(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DoubleCounter.contract.Transact(opts, "increase") -} - -// Increase is a paid mutator transaction binding the contract method 0xe8927fbc. -// -// Solidity: function increase() returns() -func (_DoubleCounter *DoubleCounterSession) Increase() (*types.Transaction, error) { - return _DoubleCounter.Contract.Increase(&_DoubleCounter.TransactOpts) -} - -// Increase is a paid mutator transaction binding the contract method 0xe8927fbc. -// -// Solidity: function increase() returns() -func (_DoubleCounter *DoubleCounterTransactorSession) Increase() (*types.Transaction, error) { - return _DoubleCounter.Contract.Increase(&_DoubleCounter.TransactOpts) -} diff --git a/x/evm/contracts/double_counter/DoubleCounter.sol b/x/evm/contracts/double_counter/DoubleCounter.sol deleted file mode 100644 index fe3cfed..0000000 --- a/x/evm/contracts/double_counter/DoubleCounter.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -contract DoubleCounter { - uint256 public count; - - function increase() external { - count+=2; - } -} diff --git a/x/evm/contracts/erc20/ERC20.go b/x/evm/contracts/erc20/ERC20.go new file mode 100644 index 0000000..ba6e88c --- /dev/null +++ b/x/evm/contracts/erc20/ERC20.go @@ -0,0 +1,1007 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc20 + +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 +) + +// Erc20MetaData contains all meta data concerning the Erc20 contract. +var Erc20MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801562000010575f80fd5b5060405162001946380380620019468339818101604052810190620000369190620002da565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060f173ffffffffffffffffffffffffffffffffffffffff16635e6c57596040518163ffffffff1660e01b81526004015f604051808303815f87803b158015620000bc575f80fd5b505af1158015620000cf573d5f803e3d5ffd5b505050508260039081620000e49190620005a8565b508160049081620000f69190620005a8565b508060055f6101000a81548160ff021916908360ff1602179055505050506200068c565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200017b8262000133565b810181811067ffffffffffffffff821117156200019d576200019c62000143565b5b80604052505050565b5f620001b16200011a565b9050620001bf828262000170565b919050565b5f67ffffffffffffffff821115620001e157620001e062000143565b5b620001ec8262000133565b9050602081019050919050565b5f5b8381101562000218578082015181840152602081019050620001fb565b5f8484015250505050565b5f620002396200023384620001c4565b620001a6565b9050828152602081018484840111156200025857620002576200012f565b5b62000265848285620001f9565b509392505050565b5f82601f8301126200028457620002836200012b565b5b81516200029684826020860162000223565b91505092915050565b5f60ff82169050919050565b620002b6816200029f565b8114620002c1575f80fd5b50565b5f81519050620002d481620002ab565b92915050565b5f805f60608486031215620002f457620002f362000123565b5b5f84015167ffffffffffffffff81111562000314576200031362000127565b5b62000322868287016200026d565b935050602084015167ffffffffffffffff81111562000346576200034562000127565b5b62000354868287016200026d565b92505060406200036786828701620002c4565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620003c057607f821691505b602082108103620003d657620003d56200037b565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026200043a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620003fd565b620004468683620003fd565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004906200048a62000484846200045e565b62000467565b6200045e565b9050919050565b5f819050919050565b620004ab8362000470565b620004c3620004ba8262000497565b84845462000409565b825550505050565b5f90565b620004d9620004cb565b620004e6818484620004a0565b505050565b5b818110156200050d57620005015f82620004cf565b600181019050620004ec565b5050565b601f8211156200055c576200052681620003dc565b6200053184620003ee565b8101602085101562000541578190505b620005596200055085620003ee565b830182620004eb565b50505b505050565b5f82821c905092915050565b5f6200057e5f198460080262000561565b1980831691505092915050565b5f6200059883836200056d565b9150826002028217905092915050565b620005b38262000371565b67ffffffffffffffff811115620005cf57620005ce62000143565b5b620005db8254620003a8565b620005e882828562000511565b5f60209050601f8311600181146200061e575f841562000609578287015190505b6200061585826200058b565b86555062000684565b601f1984166200062e86620003dc565b5f5b82811015620006575784890151825560018201915060208501945060208101905062000630565b8683101562000677578489015162000673601f8916826200056d565b8355505b6001600288020188555050505b505050505050565b6112ac806200069a5f395ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac14610213578063a9059cbb1461022f578063dd62ed3e1461025f578063f2fde38b1461028f576100cd565b806370a08231146101a75780638da5cb5b146101d757806395d89b41146101f5576100cd565b806306fdde03146100d1578063095ea7b3146100ef57806318160ddd1461011f57806323b872dd1461013d578063313ce5671461016d57806340c10f191461018b575b5f80fd5b6100d96102ab565b6040516100e69190610ed2565b60405180910390f35b61010960048036038101906101049190610f83565b610337565b6040516101169190610fdb565b60405180910390f35b610127610424565b6040516101349190611003565b60405180910390f35b6101576004803603810190610152919061101c565b61042a565b6040516101649190610fdb565b60405180910390f35b6101756106b6565b6040516101829190611087565b60405180910390f35b6101a560048036038101906101a09190610f83565b6106c8565b005b6101c160048036038101906101bc91906110a0565b61072c565b6040516101ce9190611003565b60405180910390f35b6101df610741565b6040516101ec91906110da565b60405180910390f35b6101fd610764565b60405161020a9190610ed2565b60405180910390f35b61022d60048036038101906102289190610f83565b6107f0565b005b61024960048036038101906102449190610f83565b610854565b6040516102569190610fdb565b60405180910390f35b610279600480360381019061027491906110f3565b610a51565b6040516102869190611003565b60405180910390f35b6102a960048036038101906102a491906110a0565b610a71565b005b600380546102b89061115e565b80601f01602080910402602001604051908101604052809291908181526020018280546102e49061115e565b801561032f5780601f106103065761010080835404028352916020019161032f565b820191905f5260205f20905b81548152906001019060200180831161031257829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104129190611003565b60405180910390a36001905092915050565b60065481565b5f8260f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b815260040161046691906110da565b602060405180830381865afa158015610481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a591906111b8565b6105115760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016104e391906110da565b5f604051808303815f87803b1580156104fa575f80fd5b505af115801561050c573d5f803e3d5ffd5b505050505b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105989190611210565b925050819055508260015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105eb9190611210565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461063e9190611243565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516106a29190611003565b60405180910390a360019150509392505050565b60055f9054906101000a900460ff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461071e575f80fd5b6107288282610bb9565b5050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107719061115e565b80601f016020809104026020016040519081016040528092919081815260200182805461079d9061115e565b80156107e85780601f106107bf576101008083540402835291602001916107e8565b820191905f5260205f20905b8154815290600101906020018083116107cb57829003601f168201915b505050505081565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610846575f80fd5b6108508282610d74565b5050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b815260040161089091906110da565b602060405180830381865afa1580156108ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108cf91906111b8565b61093b5760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b815260040161090d91906110da565b5f604051808303815f87803b158015610924575f80fd5b505af1158015610936573d5f803e3d5ffd5b505050505b8260015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109879190611210565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109da9190611243565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610a3e9190611003565b60405180910390a3600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ac7575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610afe575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610bf491906110da565b602060405180830381865afa158015610c0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c3391906111b8565b610c9f5760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c7191906110da565b5f604051808303815f87803b158015610c88575f80fd5b505af1158015610c9a573d5f803e3d5ffd5b505050505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610ceb9190611243565b925050819055508160065f828254610d039190611243565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d679190611003565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610dc09190611210565b925050819055508060065f828254610dd89190611210565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e3c9190611003565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610e7f578082015181840152602081019050610e64565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610ea482610e48565b610eae8185610e52565b9350610ebe818560208601610e62565b610ec781610e8a565b840191505092915050565b5f6020820190508181035f830152610eea8184610e9a565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f1f82610ef6565b9050919050565b610f2f81610f15565b8114610f39575f80fd5b50565b5f81359050610f4a81610f26565b92915050565b5f819050919050565b610f6281610f50565b8114610f6c575f80fd5b50565b5f81359050610f7d81610f59565b92915050565b5f8060408385031215610f9957610f98610ef2565b5b5f610fa685828601610f3c565b9250506020610fb785828601610f6f565b9150509250929050565b5f8115159050919050565b610fd581610fc1565b82525050565b5f602082019050610fee5f830184610fcc565b92915050565b610ffd81610f50565b82525050565b5f6020820190506110165f830184610ff4565b92915050565b5f805f6060848603121561103357611032610ef2565b5b5f61104086828701610f3c565b935050602061105186828701610f3c565b925050604061106286828701610f6f565b9150509250925092565b5f60ff82169050919050565b6110818161106c565b82525050565b5f60208201905061109a5f830184611078565b92915050565b5f602082840312156110b5576110b4610ef2565b5b5f6110c284828501610f3c565b91505092915050565b6110d481610f15565b82525050565b5f6020820190506110ed5f8301846110cb565b92915050565b5f806040838503121561110957611108610ef2565b5b5f61111685828601610f3c565b925050602061112785828601610f3c565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061117557607f821691505b60208210810361118857611187611131565b5b50919050565b61119781610fc1565b81146111a1575f80fd5b50565b5f815190506111b28161118e565b92915050565b5f602082840312156111cd576111cc610ef2565b5b5f6111da848285016111a4565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61121a82610f50565b915061122583610f50565b925082820390508181111561123d5761123c6111e3565b5b92915050565b5f61124d82610f50565b915061125883610f50565b92508282019050808211156112705761126f6111e3565b5b9291505056fea2646970667358221220375d44c965c25a7dfdde98040d0d1de94551c8ae9a657188fb3b75bf23a1e9ba64736f6c63430008180033", +} + +// Erc20ABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc20MetaData.ABI instead. +var Erc20ABI = Erc20MetaData.ABI + +// Erc20Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use Erc20MetaData.Bin instead. +var Erc20Bin = Erc20MetaData.Bin + +// DeployErc20 deploys a new Ethereum contract, binding an instance of Erc20 to it. +func DeployErc20(auth *bind.TransactOpts, backend bind.ContractBackend, _name string, _symbol string, _decimals uint8) (common.Address, *types.Transaction, *Erc20, error) { + parsed, err := Erc20MetaData.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(Erc20Bin), backend, _name, _symbol, _decimals) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Erc20{Erc20Caller: Erc20Caller{contract: contract}, Erc20Transactor: Erc20Transactor{contract: contract}, Erc20Filterer: Erc20Filterer{contract: contract}}, nil +} + +// Erc20 is an auto generated Go binding around an Ethereum contract. +type Erc20 struct { + Erc20Caller // Read-only binding to the contract + Erc20Transactor // Write-only binding to the contract + Erc20Filterer // Log filterer for contract events +} + +// Erc20Caller is an auto generated read-only Go binding around an Ethereum contract. +type Erc20Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc20Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc20Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc20Session struct { + Contract *Erc20 // 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 +} + +// Erc20CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc20CallerSession struct { + Contract *Erc20Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc20TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc20TransactorSession struct { + Contract *Erc20Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20Raw is an auto generated low-level Go binding around an Ethereum contract. +type Erc20Raw struct { + Contract *Erc20 // Generic contract binding to access the raw methods on +} + +// Erc20CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc20CallerRaw struct { + Contract *Erc20Caller // Generic read-only contract binding to access the raw methods on +} + +// Erc20TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc20TransactorRaw struct { + Contract *Erc20Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc20 creates a new instance of Erc20, bound to a specific deployed contract. +func NewErc20(address common.Address, backend bind.ContractBackend) (*Erc20, error) { + contract, err := bindErc20(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc20{Erc20Caller: Erc20Caller{contract: contract}, Erc20Transactor: Erc20Transactor{contract: contract}, Erc20Filterer: Erc20Filterer{contract: contract}}, nil +} + +// NewErc20Caller creates a new read-only instance of Erc20, bound to a specific deployed contract. +func NewErc20Caller(address common.Address, caller bind.ContractCaller) (*Erc20Caller, error) { + contract, err := bindErc20(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc20Caller{contract: contract}, nil +} + +// NewErc20Transactor creates a new write-only instance of Erc20, bound to a specific deployed contract. +func NewErc20Transactor(address common.Address, transactor bind.ContractTransactor) (*Erc20Transactor, error) { + contract, err := bindErc20(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc20Transactor{contract: contract}, nil +} + +// NewErc20Filterer creates a new log filterer instance of Erc20, bound to a specific deployed contract. +func NewErc20Filterer(address common.Address, filterer bind.ContractFilterer) (*Erc20Filterer, error) { + contract, err := bindErc20(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc20Filterer{contract: contract}, nil +} + +// bindErc20 binds a generic wrapper to an already deployed contract. +func bindErc20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Erc20MetaData.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 (_Erc20 *Erc20Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20.Contract.Erc20Caller.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 (_Erc20 *Erc20Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20.Contract.Erc20Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20 *Erc20Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20.Contract.Erc20Transactor.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 (_Erc20 *Erc20CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20.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 (_Erc20 *Erc20TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20 *Erc20TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Erc20 *Erc20Caller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "allowance", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Erc20 *Erc20Session) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Erc20.Contract.Allowance(&_Erc20.CallOpts, arg0, arg1) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Erc20 *Erc20CallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Erc20.Contract.Allowance(&_Erc20.CallOpts, arg0, arg1) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Erc20 *Erc20Caller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "balanceOf", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Erc20 *Erc20Session) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Erc20.Contract.BalanceOf(&_Erc20.CallOpts, arg0) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Erc20 *Erc20CallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Erc20.Contract.BalanceOf(&_Erc20.CallOpts, arg0) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20Caller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20Session) Decimals() (uint8, error) { + return _Erc20.Contract.Decimals(&_Erc20.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Erc20 *Erc20CallerSession) Decimals() (uint8, error) { + return _Erc20.Contract.Decimals(&_Erc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20Session) Name() (string, error) { + return _Erc20.Contract.Name(&_Erc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Erc20 *Erc20CallerSession) Name() (string, error) { + return _Erc20.Contract.Name(&_Erc20.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20 *Erc20Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Erc20.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 (_Erc20 *Erc20Session) Owner() (common.Address, error) { + return _Erc20.Contract.Owner(&_Erc20.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Erc20 *Erc20CallerSession) Owner() (common.Address, error) { + return _Erc20.Contract.Owner(&_Erc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20Session) Symbol() (string, error) { + return _Erc20.Contract.Symbol(&_Erc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Erc20 *Erc20CallerSession) Symbol() (string, error) { + return _Erc20.Contract.Symbol(&_Erc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Erc20.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20Session) TotalSupply() (*big.Int, error) { + return _Erc20.Contract.TotalSupply(&_Erc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Erc20 *Erc20CallerSession) TotalSupply() (*big.Int, error) { + return _Erc20.Contract.TotalSupply(&_Erc20.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "approve", spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Approve(&_Erc20.TransactOpts, spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Approve(&_Erc20.TransactOpts, spender, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) Burn(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "burn", from, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Session) Burn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Burn(&_Erc20.TransactOpts, from, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address from, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) Burn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Burn(&_Erc20.TransactOpts, from, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) Mint(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "mint", to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Session) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Mint(&_Erc20.TransactOpts, to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Mint(&_Erc20.TransactOpts, to, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) Transfer(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transfer", recipient, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) Transfer(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Transfer(&_Erc20.TransactOpts, recipient, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) Transfer(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.Transfer(&_Erc20.TransactOpts, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20Transactor) TransferFrom(opts *bind.TransactOpts, sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transferFrom", sender, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20Session) TransferFrom(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.TransferFrom(&_Erc20.TransactOpts, sender, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_Erc20 *Erc20TransactorSession) TransferFrom(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.TransferFrom(&_Erc20.TransactOpts, sender, recipient, amount) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20Transactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20Session) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20.Contract.TransferOwnership(&_Erc20.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Erc20 *Erc20TransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Erc20.Contract.TransferOwnership(&_Erc20.TransactOpts, newOwner) +} + +// Erc20ApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the Erc20 contract. +type Erc20ApprovalIterator struct { + Event *Erc20Approval // 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 *Erc20ApprovalIterator) 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(Erc20Approval) + 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(Erc20Approval) + 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 *Erc20ApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20ApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20Approval represents a Approval event raised by the Erc20 contract. +type Erc20Approval struct { + Owner common.Address + Spender common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*Erc20ApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _Erc20.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &Erc20ApprovalIterator{contract: _Erc20.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *Erc20Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _Erc20.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) + 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(Erc20Approval) + if err := _Erc20.contract.UnpackLog(event, "Approval", 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 +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_Erc20 *Erc20Filterer) ParseApproval(log types.Log) (*Erc20Approval, error) { + event := new(Erc20Approval) + if err := _Erc20.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc20OwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Erc20 contract. +type Erc20OwnershipTransferredIterator struct { + Event *Erc20OwnershipTransferred // 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 *Erc20OwnershipTransferredIterator) 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(Erc20OwnershipTransferred) + 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(Erc20OwnershipTransferred) + 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 *Erc20OwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20OwnershipTransferred represents a OwnershipTransferred event raised by the Erc20 contract. +type Erc20OwnershipTransferred 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 (_Erc20 *Erc20Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*Erc20OwnershipTransferredIterator, 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 := _Erc20.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Erc20OwnershipTransferredIterator{contract: _Erc20.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 (_Erc20 *Erc20Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *Erc20OwnershipTransferred, 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 := _Erc20.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(Erc20OwnershipTransferred) + if err := _Erc20.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 (_Erc20 *Erc20Filterer) ParseOwnershipTransferred(log types.Log) (*Erc20OwnershipTransferred, error) { + event := new(Erc20OwnershipTransferred) + if err := _Erc20.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Erc20TransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the Erc20 contract. +type Erc20TransferIterator struct { + Event *Erc20Transfer // 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 *Erc20TransferIterator) 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(Erc20Transfer) + 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(Erc20Transfer) + 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 *Erc20TransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Erc20TransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Erc20Transfer represents a Transfer event raised by the Erc20 contract. +type Erc20Transfer struct { + From common.Address + To common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*Erc20TransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc20.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &Erc20TransferIterator{contract: _Erc20.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *Erc20Transfer, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Erc20.contract.WatchLogs(opts, "Transfer", fromRule, toRule) + 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(Erc20Transfer) + if err := _Erc20.contract.UnpackLog(event, "Transfer", 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 +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_Erc20 *Erc20Filterer) ParseTransfer(log types.Log) (*Erc20Transfer, error) { + event := new(Erc20Transfer) + if err := _Erc20.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/x/evm/contracts/erc20/ERC20.sol b/x/evm/contracts/erc20/ERC20.sol new file mode 100644 index 0000000..543648c --- /dev/null +++ b/x/evm/contracts/erc20/ERC20.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../i_erc20/IERC20.sol"; +import "../ownable/Ownable.sol"; +import "../erc20_registry/ERC20Registry.sol"; + +contract ERC20 is IERC20, Ownable, ERC20Registry { + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + string public name; + string public symbol; + uint8 public decimals; + uint256 public totalSupply; + + constructor(string memory _name, string memory _symbol, uint8 _decimals) register_erc20 { + name = _name; + symbol = _symbol; + decimals = _decimals; + } + + function transfer( + address recipient, + uint256 amount + ) external register_erc20_store(recipient) returns (bool) { + balanceOf[msg.sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(msg.sender, recipient, amount); + return true; + } + + function approve(address spender, uint256 amount) external returns (bool) { + allowance[msg.sender][spender] = amount; + emit Approval(msg.sender, spender, amount); + return true; + } + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external register_erc20_store(recipient) returns (bool) { + allowance[sender][msg.sender] -= amount; + balanceOf[sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(sender, recipient, amount); + return true; + } + + function _mint(address to, uint256 amount) internal register_erc20_store(to) { + balanceOf[to] += amount; + totalSupply += amount; + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + totalSupply -= amount; + emit Transfer(from, address(0), amount); + } + + function mint(address to, uint256 amount) external onlyOwner{ + _mint(to, amount); + } + + function burn(address from, uint256 amount) external onlyOwner { + _burn(from, amount); + } +} diff --git a/x/evm/contracts/erc20_registry/ERC20Registry.go b/x/evm/contracts/erc20_registry/ERC20Registry.go new file mode 100644 index 0000000..58840fb --- /dev/null +++ b/x/evm/contracts/erc20_registry/ERC20Registry.go @@ -0,0 +1,203 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc20_registry + +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 +) + +// Erc20RegistryMetaData contains all meta data concerning the Erc20Registry contract. +var Erc20RegistryMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea264697066735822122030aa80545713f6ecc82346bb6aa0d43d3e45ae18fdeceb8d6e53b211854fb54064736f6c63430008180033", +} + +// Erc20RegistryABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc20RegistryMetaData.ABI instead. +var Erc20RegistryABI = Erc20RegistryMetaData.ABI + +// Erc20RegistryBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use Erc20RegistryMetaData.Bin instead. +var Erc20RegistryBin = Erc20RegistryMetaData.Bin + +// DeployErc20Registry deploys a new Ethereum contract, binding an instance of Erc20Registry to it. +func DeployErc20Registry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Erc20Registry, error) { + parsed, err := Erc20RegistryMetaData.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(Erc20RegistryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Erc20Registry{Erc20RegistryCaller: Erc20RegistryCaller{contract: contract}, Erc20RegistryTransactor: Erc20RegistryTransactor{contract: contract}, Erc20RegistryFilterer: Erc20RegistryFilterer{contract: contract}}, nil +} + +// Erc20Registry is an auto generated Go binding around an Ethereum contract. +type Erc20Registry struct { + Erc20RegistryCaller // Read-only binding to the contract + Erc20RegistryTransactor // Write-only binding to the contract + Erc20RegistryFilterer // Log filterer for contract events +} + +// Erc20RegistryCaller is an auto generated read-only Go binding around an Ethereum contract. +type Erc20RegistryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20RegistryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc20RegistryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20RegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc20RegistryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20RegistrySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc20RegistrySession struct { + Contract *Erc20Registry // 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 +} + +// Erc20RegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc20RegistryCallerSession struct { + Contract *Erc20RegistryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc20RegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc20RegistryTransactorSession struct { + Contract *Erc20RegistryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20RegistryRaw is an auto generated low-level Go binding around an Ethereum contract. +type Erc20RegistryRaw struct { + Contract *Erc20Registry // Generic contract binding to access the raw methods on +} + +// Erc20RegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc20RegistryCallerRaw struct { + Contract *Erc20RegistryCaller // Generic read-only contract binding to access the raw methods on +} + +// Erc20RegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc20RegistryTransactorRaw struct { + Contract *Erc20RegistryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc20Registry creates a new instance of Erc20Registry, bound to a specific deployed contract. +func NewErc20Registry(address common.Address, backend bind.ContractBackend) (*Erc20Registry, error) { + contract, err := bindErc20Registry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc20Registry{Erc20RegistryCaller: Erc20RegistryCaller{contract: contract}, Erc20RegistryTransactor: Erc20RegistryTransactor{contract: contract}, Erc20RegistryFilterer: Erc20RegistryFilterer{contract: contract}}, nil +} + +// NewErc20RegistryCaller creates a new read-only instance of Erc20Registry, bound to a specific deployed contract. +func NewErc20RegistryCaller(address common.Address, caller bind.ContractCaller) (*Erc20RegistryCaller, error) { + contract, err := bindErc20Registry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc20RegistryCaller{contract: contract}, nil +} + +// NewErc20RegistryTransactor creates a new write-only instance of Erc20Registry, bound to a specific deployed contract. +func NewErc20RegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*Erc20RegistryTransactor, error) { + contract, err := bindErc20Registry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc20RegistryTransactor{contract: contract}, nil +} + +// NewErc20RegistryFilterer creates a new log filterer instance of Erc20Registry, bound to a specific deployed contract. +func NewErc20RegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*Erc20RegistryFilterer, error) { + contract, err := bindErc20Registry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc20RegistryFilterer{contract: contract}, nil +} + +// bindErc20Registry binds a generic wrapper to an already deployed contract. +func bindErc20Registry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Erc20RegistryMetaData.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 (_Erc20Registry *Erc20RegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Registry.Contract.Erc20RegistryCaller.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 (_Erc20Registry *Erc20RegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Registry.Contract.Erc20RegistryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Registry *Erc20RegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Registry.Contract.Erc20RegistryTransactor.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 (_Erc20Registry *Erc20RegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Registry.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 (_Erc20Registry *Erc20RegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Registry.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Registry *Erc20RegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Registry.Contract.contract.Transact(opts, method, params...) +} diff --git a/x/evm/contracts/erc20_registry/ERC20Registry.sol b/x/evm/contracts/erc20_registry/ERC20Registry.sol new file mode 100644 index 0000000..44fca22 --- /dev/null +++ b/x/evm/contracts/erc20_registry/ERC20Registry.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../i_erc20_registry/IERC20Registry.sol"; + +/** + * @title ERC20Registry + */ +contract ERC20Registry { + modifier register_erc20() { + BECH32_CONTRACT.register_erc20(); + + _; + } + + modifier register_erc20_store(address account) { + if ( + !BECH32_CONTRACT.is_erc20_store_registered( + account + ) + ) { + BECH32_CONTRACT.register_erc20_store( + account + ); + } + + _; + } +} diff --git a/x/evm/contracts/factory/Factory.go b/x/evm/contracts/factory/Factory.go new file mode 100644 index 0000000..ea2e666 --- /dev/null +++ b/x/evm/contracts/factory/Factory.go @@ -0,0 +1,358 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package factory + +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 +) + +// FactoryMetaData contains all meta data concerning the Factory contract. +var FactoryMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"ERC20Created\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"name\":\"deployNewERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561000f575f80fd5b50611d4b8061001d5f395ff3fe608060405234801562000010575f80fd5b50600436106200002c575f3560e01c8063ba2b9c441462000030575b5f80fd5b6200004e600480360381019062000048919062000213565b62000066565b6040516200005d9190620002f6565b60405180910390f35b5f8086868686866040516200007b9062000158565b6200008b95949392919062000382565b604051809103905ff080158015620000a5573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b336040518263ffffffff1660e01b8152600401620000e39190620002f6565b5f604051808303815f87803b158015620000fb575f80fd5b505af11580156200010e573d5f803e3d5ffd5b505050507f41039c8b82bb5a365f56b4f9d87cee99e069b450bfdc3d87696fcd87783f24c181604051620001439190620002f6565b60405180910390a18091505095945050505050565b61194680620003d083390190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f8083601f8401126200019257620001916200016e565b5b8235905067ffffffffffffffff811115620001b257620001b162000172565b5b602083019150836001820283011115620001d157620001d062000176565b5b9250929050565b5f60ff82169050919050565b620001ef81620001d8565b8114620001fa575f80fd5b50565b5f813590506200020d81620001e4565b92915050565b5f805f805f606086880312156200022f576200022e62000166565b5b5f86013567ffffffffffffffff8111156200024f576200024e6200016a565b5b6200025d888289016200017a565b9550955050602086013567ffffffffffffffff8111156200028357620002826200016a565b5b62000291888289016200017a565b93509350506040620002a688828901620001fd565b9150509295509295909350565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002de82620002b3565b9050919050565b620002f081620002d2565b82525050565b5f6020820190506200030b5f830184620002e5565b92915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f6200034c838562000311565b93506200035b83858462000321565b62000366836200032f565b840190509392505050565b6200037c81620001d8565b82525050565b5f6060820190508181035f8301526200039d8187896200033f565b90508181036020830152620003b48185876200033f565b9050620003c5604083018462000371565b969550505050505056fe608060405234801562000010575f80fd5b5060405162001946380380620019468339818101604052810190620000369190620002da565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060f173ffffffffffffffffffffffffffffffffffffffff16635e6c57596040518163ffffffff1660e01b81526004015f604051808303815f87803b158015620000bc575f80fd5b505af1158015620000cf573d5f803e3d5ffd5b505050508260039081620000e49190620005a8565b508160049081620000f69190620005a8565b508060055f6101000a81548160ff021916908360ff1602179055505050506200068c565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200017b8262000133565b810181811067ffffffffffffffff821117156200019d576200019c62000143565b5b80604052505050565b5f620001b16200011a565b9050620001bf828262000170565b919050565b5f67ffffffffffffffff821115620001e157620001e062000143565b5b620001ec8262000133565b9050602081019050919050565b5f5b8381101562000218578082015181840152602081019050620001fb565b5f8484015250505050565b5f620002396200023384620001c4565b620001a6565b9050828152602081018484840111156200025857620002576200012f565b5b62000265848285620001f9565b509392505050565b5f82601f8301126200028457620002836200012b565b5b81516200029684826020860162000223565b91505092915050565b5f60ff82169050919050565b620002b6816200029f565b8114620002c1575f80fd5b50565b5f81519050620002d481620002ab565b92915050565b5f805f60608486031215620002f457620002f362000123565b5b5f84015167ffffffffffffffff81111562000314576200031362000127565b5b62000322868287016200026d565b935050602084015167ffffffffffffffff81111562000346576200034562000127565b5b62000354868287016200026d565b92505060406200036786828701620002c4565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620003c057607f821691505b602082108103620003d657620003d56200037b565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026200043a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620003fd565b620004468683620003fd565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004906200048a62000484846200045e565b62000467565b6200045e565b9050919050565b5f819050919050565b620004ab8362000470565b620004c3620004ba8262000497565b84845462000409565b825550505050565b5f90565b620004d9620004cb565b620004e6818484620004a0565b505050565b5b818110156200050d57620005015f82620004cf565b600181019050620004ec565b5050565b601f8211156200055c576200052681620003dc565b6200053184620003ee565b8101602085101562000541578190505b620005596200055085620003ee565b830182620004eb565b50505b505050565b5f82821c905092915050565b5f6200057e5f198460080262000561565b1980831691505092915050565b5f6200059883836200056d565b9150826002028217905092915050565b620005b38262000371565b67ffffffffffffffff811115620005cf57620005ce62000143565b5b620005db8254620003a8565b620005e882828562000511565b5f60209050601f8311600181146200061e575f841562000609578287015190505b6200061585826200058b565b86555062000684565b601f1984166200062e86620003dc565b5f5b82811015620006575784890151825560018201915060208501945060208101905062000630565b8683101562000677578489015162000673601f8916826200056d565b8355505b6001600288020188555050505b505050505050565b6112ac806200069a5f395ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac14610213578063a9059cbb1461022f578063dd62ed3e1461025f578063f2fde38b1461028f576100cd565b806370a08231146101a75780638da5cb5b146101d757806395d89b41146101f5576100cd565b806306fdde03146100d1578063095ea7b3146100ef57806318160ddd1461011f57806323b872dd1461013d578063313ce5671461016d57806340c10f191461018b575b5f80fd5b6100d96102ab565b6040516100e69190610ed2565b60405180910390f35b61010960048036038101906101049190610f83565b610337565b6040516101169190610fdb565b60405180910390f35b610127610424565b6040516101349190611003565b60405180910390f35b6101576004803603810190610152919061101c565b61042a565b6040516101649190610fdb565b60405180910390f35b6101756106b6565b6040516101829190611087565b60405180910390f35b6101a560048036038101906101a09190610f83565b6106c8565b005b6101c160048036038101906101bc91906110a0565b61072c565b6040516101ce9190611003565b60405180910390f35b6101df610741565b6040516101ec91906110da565b60405180910390f35b6101fd610764565b60405161020a9190610ed2565b60405180910390f35b61022d60048036038101906102289190610f83565b6107f0565b005b61024960048036038101906102449190610f83565b610854565b6040516102569190610fdb565b60405180910390f35b610279600480360381019061027491906110f3565b610a51565b6040516102869190611003565b60405180910390f35b6102a960048036038101906102a491906110a0565b610a71565b005b600380546102b89061115e565b80601f01602080910402602001604051908101604052809291908181526020018280546102e49061115e565b801561032f5780601f106103065761010080835404028352916020019161032f565b820191905f5260205f20905b81548152906001019060200180831161031257829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516104129190611003565b60405180910390a36001905092915050565b60065481565b5f8260f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b815260040161046691906110da565b602060405180830381865afa158015610481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a591906111b8565b6105115760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016104e391906110da565b5f604051808303815f87803b1580156104fa575f80fd5b505af115801561050c573d5f803e3d5ffd5b505050505b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105989190611210565b925050819055508260015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105eb9190611210565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461063e9190611243565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516106a29190611003565b60405180910390a360019150509392505050565b60055f9054906101000a900460ff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461071e575f80fd5b6107288282610bb9565b5050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107719061115e565b80601f016020809104026020016040519081016040528092919081815260200182805461079d9061115e565b80156107e85780601f106107bf576101008083540402835291602001916107e8565b820191905f5260205f20905b8154815290600101906020018083116107cb57829003601f168201915b505050505081565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610846575f80fd5b6108508282610d74565b5050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b815260040161089091906110da565b602060405180830381865afa1580156108ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108cf91906111b8565b61093b5760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b815260040161090d91906110da565b5f604051808303815f87803b158015610924575f80fd5b505af1158015610936573d5f803e3d5ffd5b505050505b8260015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109879190611210565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109da9190611243565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610a3e9190611003565b60405180910390a3600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ac7575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610afe575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f173ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610bf491906110da565b602060405180830381865afa158015610c0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c3391906111b8565b610c9f5760f173ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c7191906110da565b5f604051808303815f87803b158015610c88575f80fd5b505af1158015610c9a573d5f803e3d5ffd5b505050505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610ceb9190611243565b925050819055508160065f828254610d039190611243565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d679190611003565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610dc09190611210565b925050819055508060065f828254610dd89190611210565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e3c9190611003565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610e7f578082015181840152602081019050610e64565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610ea482610e48565b610eae8185610e52565b9350610ebe818560208601610e62565b610ec781610e8a565b840191505092915050565b5f6020820190508181035f830152610eea8184610e9a565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f1f82610ef6565b9050919050565b610f2f81610f15565b8114610f39575f80fd5b50565b5f81359050610f4a81610f26565b92915050565b5f819050919050565b610f6281610f50565b8114610f6c575f80fd5b50565b5f81359050610f7d81610f59565b92915050565b5f8060408385031215610f9957610f98610ef2565b5b5f610fa685828601610f3c565b9250506020610fb785828601610f6f565b9150509250929050565b5f8115159050919050565b610fd581610fc1565b82525050565b5f602082019050610fee5f830184610fcc565b92915050565b610ffd81610f50565b82525050565b5f6020820190506110165f830184610ff4565b92915050565b5f805f6060848603121561103357611032610ef2565b5b5f61104086828701610f3c565b935050602061105186828701610f3c565b925050604061106286828701610f6f565b9150509250925092565b5f60ff82169050919050565b6110818161106c565b82525050565b5f60208201905061109a5f830184611078565b92915050565b5f602082840312156110b5576110b4610ef2565b5b5f6110c284828501610f3c565b91505092915050565b6110d481610f15565b82525050565b5f6020820190506110ed5f8301846110cb565b92915050565b5f806040838503121561110957611108610ef2565b5b5f61111685828601610f3c565b925050602061112785828601610f3c565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061117557607f821691505b60208210810361118857611187611131565b5b50919050565b61119781610fc1565b81146111a1575f80fd5b50565b5f815190506111b28161118e565b92915050565b5f602082840312156111cd576111cc610ef2565b5b5f6111da848285016111a4565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61121a82610f50565b915061122583610f50565b925082820390508181111561123d5761123c6111e3565b5b92915050565b5f61124d82610f50565b915061125883610f50565b92508282019050808211156112705761126f6111e3565b5b9291505056fea2646970667358221220375d44c965c25a7dfdde98040d0d1de94551c8ae9a657188fb3b75bf23a1e9ba64736f6c63430008180033a26469706673582212204067c0449ce9a1971371be4da4348c4be7bb268c1f59cb345d353eb22bb9fda064736f6c63430008180033", +} + +// FactoryABI is the input ABI used to generate the binding from. +// Deprecated: Use FactoryMetaData.ABI instead. +var FactoryABI = FactoryMetaData.ABI + +// FactoryBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use FactoryMetaData.Bin instead. +var FactoryBin = FactoryMetaData.Bin + +// DeployFactory deploys a new Ethereum contract, binding an instance of Factory to it. +func DeployFactory(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Factory, error) { + parsed, err := FactoryMetaData.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(FactoryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Factory{FactoryCaller: FactoryCaller{contract: contract}, FactoryTransactor: FactoryTransactor{contract: contract}, FactoryFilterer: FactoryFilterer{contract: contract}}, nil +} + +// Factory is an auto generated Go binding around an Ethereum contract. +type Factory struct { + FactoryCaller // Read-only binding to the contract + FactoryTransactor // Write-only binding to the contract + FactoryFilterer // Log filterer for contract events +} + +// FactoryCaller is an auto generated read-only Go binding around an Ethereum contract. +type FactoryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// FactoryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type FactoryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// FactoryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type FactoryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// FactorySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type FactorySession struct { + Contract *Factory // 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 +} + +// FactoryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type FactoryCallerSession struct { + Contract *FactoryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// FactoryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type FactoryTransactorSession struct { + Contract *FactoryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// FactoryRaw is an auto generated low-level Go binding around an Ethereum contract. +type FactoryRaw struct { + Contract *Factory // Generic contract binding to access the raw methods on +} + +// FactoryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type FactoryCallerRaw struct { + Contract *FactoryCaller // Generic read-only contract binding to access the raw methods on +} + +// FactoryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type FactoryTransactorRaw struct { + Contract *FactoryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewFactory creates a new instance of Factory, bound to a specific deployed contract. +func NewFactory(address common.Address, backend bind.ContractBackend) (*Factory, error) { + contract, err := bindFactory(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Factory{FactoryCaller: FactoryCaller{contract: contract}, FactoryTransactor: FactoryTransactor{contract: contract}, FactoryFilterer: FactoryFilterer{contract: contract}}, nil +} + +// NewFactoryCaller creates a new read-only instance of Factory, bound to a specific deployed contract. +func NewFactoryCaller(address common.Address, caller bind.ContractCaller) (*FactoryCaller, error) { + contract, err := bindFactory(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &FactoryCaller{contract: contract}, nil +} + +// NewFactoryTransactor creates a new write-only instance of Factory, bound to a specific deployed contract. +func NewFactoryTransactor(address common.Address, transactor bind.ContractTransactor) (*FactoryTransactor, error) { + contract, err := bindFactory(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &FactoryTransactor{contract: contract}, nil +} + +// NewFactoryFilterer creates a new log filterer instance of Factory, bound to a specific deployed contract. +func NewFactoryFilterer(address common.Address, filterer bind.ContractFilterer) (*FactoryFilterer, error) { + contract, err := bindFactory(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &FactoryFilterer{contract: contract}, nil +} + +// bindFactory binds a generic wrapper to an already deployed contract. +func bindFactory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FactoryMetaData.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 (_Factory *FactoryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Factory.Contract.FactoryCaller.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 (_Factory *FactoryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Factory.Contract.FactoryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Factory *FactoryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Factory.Contract.FactoryTransactor.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 (_Factory *FactoryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Factory.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 (_Factory *FactoryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Factory.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Factory *FactoryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Factory.Contract.contract.Transact(opts, method, params...) +} + +// DeployNewERC20 is a paid mutator transaction binding the contract method 0xba2b9c44. +// +// Solidity: function deployNewERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Factory *FactoryTransactor) DeployNewERC20(opts *bind.TransactOpts, name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Factory.contract.Transact(opts, "deployNewERC20", name, symbol, decimals) +} + +// DeployNewERC20 is a paid mutator transaction binding the contract method 0xba2b9c44. +// +// Solidity: function deployNewERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Factory *FactorySession) DeployNewERC20(name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Factory.Contract.DeployNewERC20(&_Factory.TransactOpts, name, symbol, decimals) +} + +// DeployNewERC20 is a paid mutator transaction binding the contract method 0xba2b9c44. +// +// Solidity: function deployNewERC20(string name, string symbol, uint8 decimals) returns(address) +func (_Factory *FactoryTransactorSession) DeployNewERC20(name string, symbol string, decimals uint8) (*types.Transaction, error) { + return _Factory.Contract.DeployNewERC20(&_Factory.TransactOpts, name, symbol, decimals) +} + +// FactoryERC20CreatedIterator is returned from FilterERC20Created and is used to iterate over the raw logs and unpacked data for ERC20Created events raised by the Factory contract. +type FactoryERC20CreatedIterator struct { + Event *FactoryERC20Created // 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 *FactoryERC20CreatedIterator) 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(FactoryERC20Created) + 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(FactoryERC20Created) + 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 *FactoryERC20CreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *FactoryERC20CreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// FactoryERC20Created represents a ERC20Created event raised by the Factory contract. +type FactoryERC20Created struct { + TokenAddress common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterERC20Created is a free log retrieval operation binding the contract event 0x41039c8b82bb5a365f56b4f9d87cee99e069b450bfdc3d87696fcd87783f24c1. +// +// Solidity: event ERC20Created(address tokenAddress) +func (_Factory *FactoryFilterer) FilterERC20Created(opts *bind.FilterOpts) (*FactoryERC20CreatedIterator, error) { + + logs, sub, err := _Factory.contract.FilterLogs(opts, "ERC20Created") + if err != nil { + return nil, err + } + return &FactoryERC20CreatedIterator{contract: _Factory.contract, event: "ERC20Created", logs: logs, sub: sub}, nil +} + +// WatchERC20Created is a free log subscription operation binding the contract event 0x41039c8b82bb5a365f56b4f9d87cee99e069b450bfdc3d87696fcd87783f24c1. +// +// Solidity: event ERC20Created(address tokenAddress) +func (_Factory *FactoryFilterer) WatchERC20Created(opts *bind.WatchOpts, sink chan<- *FactoryERC20Created) (event.Subscription, error) { + + logs, sub, err := _Factory.contract.WatchLogs(opts, "ERC20Created") + 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(FactoryERC20Created) + if err := _Factory.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 0x41039c8b82bb5a365f56b4f9d87cee99e069b450bfdc3d87696fcd87783f24c1. +// +// Solidity: event ERC20Created(address tokenAddress) +func (_Factory *FactoryFilterer) ParseERC20Created(log types.Log) (*FactoryERC20Created, error) { + event := new(FactoryERC20Created) + if err := _Factory.contract.UnpackLog(event, "ERC20Created", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/x/evm/contracts/factory/Factory.sol b/x/evm/contracts/factory/Factory.sol new file mode 100644 index 0000000..bb68598 --- /dev/null +++ b/x/evm/contracts/factory/Factory.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import "../erc20/ERC20.sol"; + +contract Factory { + event ERC20Created(address tokenAddress); + + function deployNewERC20( + string calldata name, + string calldata symbol, + uint8 decimals + ) external returns (address) { + ERC20 t = new ERC20(name, symbol, decimals); + t.transferOwnership(msg.sender); + + emit ERC20Created(address(t)); + + return address(t); + } +} diff --git a/x/evm/contracts/i_erc20/IERC20.go b/x/evm/contracts/i_erc20/IERC20.go new file mode 100644 index 0000000..f435766 --- /dev/null +++ b/x/evm/contracts/i_erc20/IERC20.go @@ -0,0 +1,430 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package i_erc20 + +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 +) + +// IErc20MetaData contains all meta data concerning the IErc20 contract. +var IErc20MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IErc20ABI is the input ABI used to generate the binding from. +// Deprecated: Use IErc20MetaData.ABI instead. +var IErc20ABI = IErc20MetaData.ABI + +// IErc20 is an auto generated Go binding around an Ethereum contract. +type IErc20 struct { + IErc20Caller // Read-only binding to the contract + IErc20Transactor // Write-only binding to the contract + IErc20Filterer // Log filterer for contract events +} + +// IErc20Caller is an auto generated read-only Go binding around an Ethereum contract. +type IErc20Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20Transactor is an auto generated write-only Go binding around an Ethereum contract. +type IErc20Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IErc20Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IErc20Session struct { + Contract *IErc20 // 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 +} + +// IErc20CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IErc20CallerSession struct { + Contract *IErc20Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IErc20TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IErc20TransactorSession struct { + Contract *IErc20Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IErc20Raw is an auto generated low-level Go binding around an Ethereum contract. +type IErc20Raw struct { + Contract *IErc20 // Generic contract binding to access the raw methods on +} + +// IErc20CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IErc20CallerRaw struct { + Contract *IErc20Caller // Generic read-only contract binding to access the raw methods on +} + +// IErc20TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IErc20TransactorRaw struct { + Contract *IErc20Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewIErc20 creates a new instance of IErc20, bound to a specific deployed contract. +func NewIErc20(address common.Address, backend bind.ContractBackend) (*IErc20, error) { + contract, err := bindIErc20(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IErc20{IErc20Caller: IErc20Caller{contract: contract}, IErc20Transactor: IErc20Transactor{contract: contract}, IErc20Filterer: IErc20Filterer{contract: contract}}, nil +} + +// NewIErc20Caller creates a new read-only instance of IErc20, bound to a specific deployed contract. +func NewIErc20Caller(address common.Address, caller bind.ContractCaller) (*IErc20Caller, error) { + contract, err := bindIErc20(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IErc20Caller{contract: contract}, nil +} + +// NewIErc20Transactor creates a new write-only instance of IErc20, bound to a specific deployed contract. +func NewIErc20Transactor(address common.Address, transactor bind.ContractTransactor) (*IErc20Transactor, error) { + contract, err := bindIErc20(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IErc20Transactor{contract: contract}, nil +} + +// NewIErc20Filterer creates a new log filterer instance of IErc20, bound to a specific deployed contract. +func NewIErc20Filterer(address common.Address, filterer bind.ContractFilterer) (*IErc20Filterer, error) { + contract, err := bindIErc20(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IErc20Filterer{contract: contract}, nil +} + +// bindIErc20 binds a generic wrapper to an already deployed contract. +func bindIErc20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IErc20MetaData.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 (_IErc20 *IErc20Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IErc20.Contract.IErc20Caller.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 (_IErc20 *IErc20Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IErc20.Contract.IErc20Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IErc20 *IErc20Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IErc20.Contract.IErc20Transactor.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 (_IErc20 *IErc20CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IErc20.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 (_IErc20 *IErc20TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IErc20.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IErc20 *IErc20TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IErc20.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_IErc20 *IErc20Caller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "allowance", owner, spender) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_IErc20 *IErc20Session) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _IErc20.Contract.Allowance(&_IErc20.CallOpts, owner, spender) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_IErc20 *IErc20CallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _IErc20.Contract.Allowance(&_IErc20.CallOpts, owner, spender) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_IErc20 *IErc20Caller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_IErc20 *IErc20Session) BalanceOf(account common.Address) (*big.Int, error) { + return _IErc20.Contract.BalanceOf(&_IErc20.CallOpts, account) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_IErc20 *IErc20CallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _IErc20.Contract.BalanceOf(&_IErc20.CallOpts, account) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_IErc20 *IErc20Caller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_IErc20 *IErc20Session) Decimals() (uint8, error) { + return _IErc20.Contract.Decimals(&_IErc20.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_IErc20 *IErc20CallerSession) Decimals() (uint8, error) { + return _IErc20.Contract.Decimals(&_IErc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_IErc20 *IErc20Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_IErc20 *IErc20Session) Name() (string, error) { + return _IErc20.Contract.Name(&_IErc20.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_IErc20 *IErc20CallerSession) Name() (string, error) { + return _IErc20.Contract.Name(&_IErc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_IErc20 *IErc20Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_IErc20 *IErc20Session) Symbol() (string, error) { + return _IErc20.Contract.Symbol(&_IErc20.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_IErc20 *IErc20CallerSession) Symbol() (string, error) { + return _IErc20.Contract.Symbol(&_IErc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_IErc20 *IErc20Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _IErc20.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_IErc20 *IErc20Session) TotalSupply() (*big.Int, error) { + return _IErc20.Contract.TotalSupply(&_IErc20.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_IErc20 *IErc20CallerSession) TotalSupply() (*big.Int, error) { + return _IErc20.Contract.TotalSupply(&_IErc20.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_IErc20 *IErc20Transactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.contract.Transact(opts, "approve", spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_IErc20 *IErc20Session) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.Approve(&_IErc20.TransactOpts, spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_IErc20 *IErc20TransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.Approve(&_IErc20.TransactOpts, spender, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20Transactor) Transfer(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.contract.Transact(opts, "transfer", recipient, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20Session) Transfer(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.Transfer(&_IErc20.TransactOpts, recipient, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20TransactorSession) Transfer(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.Transfer(&_IErc20.TransactOpts, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20Transactor) TransferFrom(opts *bind.TransactOpts, sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.contract.Transact(opts, "transferFrom", sender, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20Session) TransferFrom(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.TransferFrom(&_IErc20.TransactOpts, sender, recipient, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address sender, address recipient, uint256 amount) returns(bool) +func (_IErc20 *IErc20TransactorSession) TransferFrom(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.TransferFrom(&_IErc20.TransactOpts, sender, recipient, amount) +} diff --git a/x/evm/contracts/i_erc20/IERC20.sol b/x/evm/contracts/i_erc20/IERC20.sol new file mode 100644 index 0000000..17bd22b --- /dev/null +++ b/x/evm/contracts/i_erc20/IERC20.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface IERC20 { + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function allowance( + address owner, + address spender + ) external view returns (uint256); + + function approve(address spender, uint256 amount) external returns (bool); + function transfer( + address recipient, + uint256 amount + ) external returns (bool); + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); +} diff --git a/x/evm/contracts/i_erc20_registry/IERC20Registry.go b/x/evm/contracts/i_erc20_registry/IERC20Registry.go new file mode 100644 index 0000000..c1f22be --- /dev/null +++ b/x/evm/contracts/i_erc20_registry/IERC20Registry.go @@ -0,0 +1,254 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package i_erc20_registry + +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 +) + +// IErc20RegistryMetaData contains all meta data concerning the IErc20Registry contract. +var IErc20RegistryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"is_erc20_store_registered\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"registered\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register_erc20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"register_erc20_store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IErc20RegistryABI is the input ABI used to generate the binding from. +// Deprecated: Use IErc20RegistryMetaData.ABI instead. +var IErc20RegistryABI = IErc20RegistryMetaData.ABI + +// IErc20Registry is an auto generated Go binding around an Ethereum contract. +type IErc20Registry struct { + IErc20RegistryCaller // Read-only binding to the contract + IErc20RegistryTransactor // Write-only binding to the contract + IErc20RegistryFilterer // Log filterer for contract events +} + +// IErc20RegistryCaller is an auto generated read-only Go binding around an Ethereum contract. +type IErc20RegistryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20RegistryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IErc20RegistryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20RegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IErc20RegistryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IErc20RegistrySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IErc20RegistrySession struct { + Contract *IErc20Registry // 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 +} + +// IErc20RegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IErc20RegistryCallerSession struct { + Contract *IErc20RegistryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IErc20RegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IErc20RegistryTransactorSession struct { + Contract *IErc20RegistryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IErc20RegistryRaw is an auto generated low-level Go binding around an Ethereum contract. +type IErc20RegistryRaw struct { + Contract *IErc20Registry // Generic contract binding to access the raw methods on +} + +// IErc20RegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IErc20RegistryCallerRaw struct { + Contract *IErc20RegistryCaller // Generic read-only contract binding to access the raw methods on +} + +// IErc20RegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IErc20RegistryTransactorRaw struct { + Contract *IErc20RegistryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIErc20Registry creates a new instance of IErc20Registry, bound to a specific deployed contract. +func NewIErc20Registry(address common.Address, backend bind.ContractBackend) (*IErc20Registry, error) { + contract, err := bindIErc20Registry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IErc20Registry{IErc20RegistryCaller: IErc20RegistryCaller{contract: contract}, IErc20RegistryTransactor: IErc20RegistryTransactor{contract: contract}, IErc20RegistryFilterer: IErc20RegistryFilterer{contract: contract}}, nil +} + +// NewIErc20RegistryCaller creates a new read-only instance of IErc20Registry, bound to a specific deployed contract. +func NewIErc20RegistryCaller(address common.Address, caller bind.ContractCaller) (*IErc20RegistryCaller, error) { + contract, err := bindIErc20Registry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IErc20RegistryCaller{contract: contract}, nil +} + +// NewIErc20RegistryTransactor creates a new write-only instance of IErc20Registry, bound to a specific deployed contract. +func NewIErc20RegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*IErc20RegistryTransactor, error) { + contract, err := bindIErc20Registry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IErc20RegistryTransactor{contract: contract}, nil +} + +// NewIErc20RegistryFilterer creates a new log filterer instance of IErc20Registry, bound to a specific deployed contract. +func NewIErc20RegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*IErc20RegistryFilterer, error) { + contract, err := bindIErc20Registry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IErc20RegistryFilterer{contract: contract}, nil +} + +// bindIErc20Registry binds a generic wrapper to an already deployed contract. +func bindIErc20Registry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IErc20RegistryMetaData.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 (_IErc20Registry *IErc20RegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IErc20Registry.Contract.IErc20RegistryCaller.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 (_IErc20Registry *IErc20RegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IErc20Registry.Contract.IErc20RegistryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IErc20Registry *IErc20RegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IErc20Registry.Contract.IErc20RegistryTransactor.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 (_IErc20Registry *IErc20RegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IErc20Registry.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 (_IErc20Registry *IErc20RegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IErc20Registry.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IErc20Registry *IErc20RegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IErc20Registry.Contract.contract.Transact(opts, method, params...) +} + +// IsErc20StoreRegistered is a free data retrieval call binding the contract method 0x4e25ab64. +// +// Solidity: function is_erc20_store_registered(address account) view returns(bool registered) +func (_IErc20Registry *IErc20RegistryCaller) IsErc20StoreRegistered(opts *bind.CallOpts, account common.Address) (bool, error) { + var out []interface{} + err := _IErc20Registry.contract.Call(opts, &out, "is_erc20_store_registered", account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsErc20StoreRegistered is a free data retrieval call binding the contract method 0x4e25ab64. +// +// Solidity: function is_erc20_store_registered(address account) view returns(bool registered) +func (_IErc20Registry *IErc20RegistrySession) IsErc20StoreRegistered(account common.Address) (bool, error) { + return _IErc20Registry.Contract.IsErc20StoreRegistered(&_IErc20Registry.CallOpts, account) +} + +// IsErc20StoreRegistered is a free data retrieval call binding the contract method 0x4e25ab64. +// +// Solidity: function is_erc20_store_registered(address account) view returns(bool registered) +func (_IErc20Registry *IErc20RegistryCallerSession) IsErc20StoreRegistered(account common.Address) (bool, error) { + return _IErc20Registry.Contract.IsErc20StoreRegistered(&_IErc20Registry.CallOpts, account) +} + +// RegisterErc20 is a paid mutator transaction binding the contract method 0x5e6c5759. +// +// Solidity: function register_erc20() returns() +func (_IErc20Registry *IErc20RegistryTransactor) RegisterErc20(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IErc20Registry.contract.Transact(opts, "register_erc20") +} + +// RegisterErc20 is a paid mutator transaction binding the contract method 0x5e6c5759. +// +// Solidity: function register_erc20() returns() +func (_IErc20Registry *IErc20RegistrySession) RegisterErc20() (*types.Transaction, error) { + return _IErc20Registry.Contract.RegisterErc20(&_IErc20Registry.TransactOpts) +} + +// RegisterErc20 is a paid mutator transaction binding the contract method 0x5e6c5759. +// +// Solidity: function register_erc20() returns() +func (_IErc20Registry *IErc20RegistryTransactorSession) RegisterErc20() (*types.Transaction, error) { + return _IErc20Registry.Contract.RegisterErc20(&_IErc20Registry.TransactOpts) +} + +// RegisterErc20Store is a paid mutator transaction binding the contract method 0xceeae52a. +// +// Solidity: function register_erc20_store(address account) returns() +func (_IErc20Registry *IErc20RegistryTransactor) RegisterErc20Store(opts *bind.TransactOpts, account common.Address) (*types.Transaction, error) { + return _IErc20Registry.contract.Transact(opts, "register_erc20_store", account) +} + +// RegisterErc20Store is a paid mutator transaction binding the contract method 0xceeae52a. +// +// Solidity: function register_erc20_store(address account) returns() +func (_IErc20Registry *IErc20RegistrySession) RegisterErc20Store(account common.Address) (*types.Transaction, error) { + return _IErc20Registry.Contract.RegisterErc20Store(&_IErc20Registry.TransactOpts, account) +} + +// RegisterErc20Store is a paid mutator transaction binding the contract method 0xceeae52a. +// +// Solidity: function register_erc20_store(address account) returns() +func (_IErc20Registry *IErc20RegistryTransactorSession) RegisterErc20Store(account common.Address) (*types.Transaction, error) { + return _IErc20Registry.Contract.RegisterErc20Store(&_IErc20Registry.TransactOpts, account) +} diff --git a/x/evm/contracts/i_erc20_registry/IERC20Registry.sol b/x/evm/contracts/i_erc20_registry/IERC20Registry.sol new file mode 100644 index 0000000..9a04a34 --- /dev/null +++ b/x/evm/contracts/i_erc20_registry/IERC20Registry.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +/// @dev The IERC20Registry contract's address. +address constant ERC20_REGISTRY_ADDRESS = 0x00000000000000000000000000000000000000f1; + +/// @dev The IERC20Registry contract's instance. +IERC20Registry constant BECH32_CONTRACT = IERC20Registry( + ERC20_REGISTRY_ADDRESS +); + +interface IERC20Registry { + function register_erc20() external; + function register_erc20_store(address account) external; + function is_erc20_store_registered( + address account + ) external view returns (bool registered); +} diff --git a/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.go b/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.go new file mode 100644 index 0000000..1c129a3 --- /dev/null +++ b/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.go @@ -0,0 +1,223 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package i_ibc_async_callback + +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 +) + +// IIbcAsyncCallbackMetaData contains all meta data concerning the IIbcAsyncCallback contract. +var IIbcAsyncCallbackMetaData = &bind.MetaData{ + ABI: "[{\"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\"}]", +} + +// IIbcAsyncCallbackABI is the input ABI used to generate the binding from. +// Deprecated: Use IIbcAsyncCallbackMetaData.ABI instead. +var IIbcAsyncCallbackABI = IIbcAsyncCallbackMetaData.ABI + +// IIbcAsyncCallback is an auto generated Go binding around an Ethereum contract. +type IIbcAsyncCallback struct { + IIbcAsyncCallbackCaller // Read-only binding to the contract + IIbcAsyncCallbackTransactor // Write-only binding to the contract + IIbcAsyncCallbackFilterer // Log filterer for contract events +} + +// IIbcAsyncCallbackCaller is an auto generated read-only Go binding around an Ethereum contract. +type IIbcAsyncCallbackCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IIbcAsyncCallbackTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IIbcAsyncCallbackTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IIbcAsyncCallbackFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IIbcAsyncCallbackFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IIbcAsyncCallbackSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IIbcAsyncCallbackSession struct { + Contract *IIbcAsyncCallback // 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 +} + +// IIbcAsyncCallbackCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IIbcAsyncCallbackCallerSession struct { + Contract *IIbcAsyncCallbackCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IIbcAsyncCallbackTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IIbcAsyncCallbackTransactorSession struct { + Contract *IIbcAsyncCallbackTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IIbcAsyncCallbackRaw is an auto generated low-level Go binding around an Ethereum contract. +type IIbcAsyncCallbackRaw struct { + Contract *IIbcAsyncCallback // Generic contract binding to access the raw methods on +} + +// IIbcAsyncCallbackCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IIbcAsyncCallbackCallerRaw struct { + Contract *IIbcAsyncCallbackCaller // Generic read-only contract binding to access the raw methods on +} + +// IIbcAsyncCallbackTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IIbcAsyncCallbackTransactorRaw struct { + Contract *IIbcAsyncCallbackTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIIbcAsyncCallback creates a new instance of IIbcAsyncCallback, bound to a specific deployed contract. +func NewIIbcAsyncCallback(address common.Address, backend bind.ContractBackend) (*IIbcAsyncCallback, error) { + contract, err := bindIIbcAsyncCallback(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IIbcAsyncCallback{IIbcAsyncCallbackCaller: IIbcAsyncCallbackCaller{contract: contract}, IIbcAsyncCallbackTransactor: IIbcAsyncCallbackTransactor{contract: contract}, IIbcAsyncCallbackFilterer: IIbcAsyncCallbackFilterer{contract: contract}}, nil +} + +// NewIIbcAsyncCallbackCaller creates a new read-only instance of IIbcAsyncCallback, bound to a specific deployed contract. +func NewIIbcAsyncCallbackCaller(address common.Address, caller bind.ContractCaller) (*IIbcAsyncCallbackCaller, error) { + contract, err := bindIIbcAsyncCallback(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IIbcAsyncCallbackCaller{contract: contract}, nil +} + +// NewIIbcAsyncCallbackTransactor creates a new write-only instance of IIbcAsyncCallback, bound to a specific deployed contract. +func NewIIbcAsyncCallbackTransactor(address common.Address, transactor bind.ContractTransactor) (*IIbcAsyncCallbackTransactor, error) { + contract, err := bindIIbcAsyncCallback(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IIbcAsyncCallbackTransactor{contract: contract}, nil +} + +// NewIIbcAsyncCallbackFilterer creates a new log filterer instance of IIbcAsyncCallback, bound to a specific deployed contract. +func NewIIbcAsyncCallbackFilterer(address common.Address, filterer bind.ContractFilterer) (*IIbcAsyncCallbackFilterer, error) { + contract, err := bindIIbcAsyncCallback(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IIbcAsyncCallbackFilterer{contract: contract}, nil +} + +// bindIIbcAsyncCallback binds a generic wrapper to an already deployed contract. +func bindIIbcAsyncCallback(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IIbcAsyncCallbackMetaData.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 (_IIbcAsyncCallback *IIbcAsyncCallbackRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IIbcAsyncCallback.Contract.IIbcAsyncCallbackCaller.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 (_IIbcAsyncCallback *IIbcAsyncCallbackRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IIbcAsyncCallbackTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IIbcAsyncCallback *IIbcAsyncCallbackRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IIbcAsyncCallbackTransactor.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 (_IIbcAsyncCallback *IIbcAsyncCallbackCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IIbcAsyncCallback.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 (_IIbcAsyncCallback *IIbcAsyncCallbackTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IIbcAsyncCallback *IIbcAsyncCallbackTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.contract.Transact(opts, method, params...) +} + +// IbcAck is a paid mutator transaction binding the contract method 0x0d4f1f9d. +// +// Solidity: function ibc_ack(uint64 callback_id, bool success) returns() +func (_IIbcAsyncCallback *IIbcAsyncCallbackTransactor) IbcAck(opts *bind.TransactOpts, callback_id uint64, success bool) (*types.Transaction, error) { + return _IIbcAsyncCallback.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 (_IIbcAsyncCallback *IIbcAsyncCallbackSession) IbcAck(callback_id uint64, success bool) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IbcAck(&_IIbcAsyncCallback.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 (_IIbcAsyncCallback *IIbcAsyncCallbackTransactorSession) IbcAck(callback_id uint64, success bool) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IbcAck(&_IIbcAsyncCallback.TransactOpts, callback_id, success) +} + +// IbcTimeout is a paid mutator transaction binding the contract method 0x31a503f0. +// +// Solidity: function ibc_timeout(uint64 callback_id) returns() +func (_IIbcAsyncCallback *IIbcAsyncCallbackTransactor) IbcTimeout(opts *bind.TransactOpts, callback_id uint64) (*types.Transaction, error) { + return _IIbcAsyncCallback.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 (_IIbcAsyncCallback *IIbcAsyncCallbackSession) IbcTimeout(callback_id uint64) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IbcTimeout(&_IIbcAsyncCallback.TransactOpts, callback_id) +} + +// IbcTimeout is a paid mutator transaction binding the contract method 0x31a503f0. +// +// Solidity: function ibc_timeout(uint64 callback_id) returns() +func (_IIbcAsyncCallback *IIbcAsyncCallbackTransactorSession) IbcTimeout(callback_id uint64) (*types.Transaction, error) { + return _IIbcAsyncCallback.Contract.IbcTimeout(&_IIbcAsyncCallback.TransactOpts, callback_id) +} diff --git a/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.sol b/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.sol new file mode 100644 index 0000000..1571ff7 --- /dev/null +++ b/x/evm/contracts/i_ibc_async_callback/IIBCAsyncCallback.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface IIBCAsyncCallback { + function ibc_ack(uint64 callback_id, bool success) external; + function ibc_timeout(uint64 callback_id) external; +} diff --git a/x/evm/contracts/ownable/Ownable.go b/x/evm/contracts/ownable/Ownable.go new file mode 100644 index 0000000..b892b71 --- /dev/null +++ b/x/evm/contracts/ownable/Ownable.go @@ -0,0 +1,408 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ownable + +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 +) + +// OwnableMetaData contains all meta data concerning the Ownable contract. +var OwnableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561000f575f80fd5b50335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102c48061005c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80638da5cb5b14610038578063f2fde38b14610056575b5f80fd5b610040610072565b60405161004d919061021c565b60405180910390f35b610070600480360381019061006b9190610263565b610095565b005b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146100eb575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610122575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610206826101dd565b9050919050565b610216816101fc565b82525050565b5f60208201905061022f5f83018461020d565b92915050565b5f80fd5b610242816101fc565b811461024c575f80fd5b50565b5f8135905061025d81610239565b92915050565b5f6020828403121561027857610277610235565b5b5f6102858482850161024f565b9150509291505056fea26469706673582212208e83c4e6217619f305e81b2a6cc58ab99452b595243201455dbcdb4186b09b8564736f6c63430008180033", +} + +// OwnableABI is the input ABI used to generate the binding from. +// Deprecated: Use OwnableMetaData.ABI instead. +var OwnableABI = OwnableMetaData.ABI + +// OwnableBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use OwnableMetaData.Bin instead. +var OwnableBin = OwnableMetaData.Bin + +// DeployOwnable deploys a new Ethereum contract, binding an instance of Ownable to it. +func DeployOwnable(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Ownable, error) { + parsed, err := OwnableMetaData.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(OwnableBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Ownable{OwnableCaller: OwnableCaller{contract: contract}, OwnableTransactor: OwnableTransactor{contract: contract}, OwnableFilterer: OwnableFilterer{contract: contract}}, nil +} + +// Ownable is an auto generated Go binding around an Ethereum contract. +type Ownable struct { + OwnableCaller // Read-only binding to the contract + OwnableTransactor // Write-only binding to the contract + OwnableFilterer // Log filterer for contract events +} + +// OwnableCaller is an auto generated read-only Go binding around an Ethereum contract. +type OwnableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OwnableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OwnableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OwnableSession struct { + Contract *Ownable // 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 +} + +// OwnableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OwnableCallerSession struct { + Contract *OwnableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OwnableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OwnableTransactorSession struct { + Contract *OwnableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableRaw is an auto generated low-level Go binding around an Ethereum contract. +type OwnableRaw struct { + Contract *Ownable // Generic contract binding to access the raw methods on +} + +// OwnableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OwnableCallerRaw struct { + Contract *OwnableCaller // Generic read-only contract binding to access the raw methods on +} + +// OwnableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OwnableTransactorRaw struct { + Contract *OwnableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOwnable creates a new instance of Ownable, bound to a specific deployed contract. +func NewOwnable(address common.Address, backend bind.ContractBackend) (*Ownable, error) { + contract, err := bindOwnable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ownable{OwnableCaller: OwnableCaller{contract: contract}, OwnableTransactor: OwnableTransactor{contract: contract}, OwnableFilterer: OwnableFilterer{contract: contract}}, nil +} + +// NewOwnableCaller creates a new read-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableCaller(address common.Address, caller bind.ContractCaller) (*OwnableCaller, error) { + contract, err := bindOwnable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OwnableCaller{contract: contract}, nil +} + +// NewOwnableTransactor creates a new write-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnableTransactor, error) { + contract, err := bindOwnable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OwnableTransactor{contract: contract}, nil +} + +// NewOwnableFilterer creates a new log filterer instance of Ownable, bound to a specific deployed contract. +func NewOwnableFilterer(address common.Address, filterer bind.ContractFilterer) (*OwnableFilterer, error) { + contract, err := bindOwnable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OwnableFilterer{contract: contract}, nil +} + +// bindOwnable binds a generic wrapper to an already deployed contract. +func bindOwnable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OwnableMetaData.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 (_Ownable *OwnableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.Contract.OwnableCaller.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 (_Ownable *OwnableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.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 (_Ownable *OwnableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.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 (_Ownable *OwnableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transact(opts, method, params...) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ownable.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 (_Ownable *OwnableSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCallerSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Ownable.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// OwnableOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Ownable contract. +type OwnableOwnershipTransferredIterator struct { + Event *OwnableOwnershipTransferred // 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 *OwnableOwnershipTransferredIterator) 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(OwnableOwnershipTransferred) + 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(OwnableOwnershipTransferred) + 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 *OwnableOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OwnableOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OwnableOwnershipTransferred represents a OwnershipTransferred event raised by the Ownable contract. +type OwnableOwnershipTransferred 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 (_Ownable *OwnableFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*OwnableOwnershipTransferredIterator, 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 := _Ownable.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &OwnableOwnershipTransferredIterator{contract: _Ownable.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 (_Ownable *OwnableFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OwnableOwnershipTransferred, 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 := _Ownable.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(OwnableOwnershipTransferred) + if err := _Ownable.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 (_Ownable *OwnableFilterer) ParseOwnershipTransferred(log types.Log) (*OwnableOwnershipTransferred, error) { + event := new(OwnableOwnershipTransferred) + if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/x/evm/contracts/ownable/Ownable.sol b/x/evm/contracts/ownable/Ownable.sol new file mode 100644 index 0000000..24e1ce3 --- /dev/null +++ b/x/evm/contracts/ownable/Ownable.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() { + owner = msg.sender; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + require(newOwner != address(0)); + emit OwnershipTransferred(owner, newOwner); + + owner = newOwner; + } +} \ No newline at end of file diff --git a/x/evm/keeper/common_test.go b/x/evm/keeper/common_test.go index 773be3c..9abffda 100644 --- a/x/evm/keeper/common_test.go +++ b/x/evm/keeper/common_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "context" "encoding/binary" "testing" "time" @@ -34,15 +35,12 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - distribution "github.com/cosmos/cosmos-sdk/x/distribution" - distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/staking" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/gogoproto/proto" + "github.com/initia-labs/minievm/x/evm" EVMConfig "github.com/initia-labs/minievm/x/evm/config" evmkeeper "github.com/initia-labs/minievm/x/evm/keeper" evmtypes "github.com/initia-labs/minievm/x/evm/types" @@ -51,8 +49,7 @@ import ( var ModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, bank.AppModuleBasic{}, - staking.AppModuleBasic{}, - distribution.AppModuleBasic{}, + evm.AppModuleBasic{}, ) var ( @@ -162,25 +159,24 @@ func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk. } type TestKeepers struct { - AccountKeeper authkeeper.AccountKeeper - StakingKeeper stakingkeeper.Keeper - DistKeeper distributionkeeper.Keeper - BankKeeper bankkeeper.Keeper - EVMKeeper evmkeeper.Keeper - EncodingConfig EncodingConfig - Faucet *TestFaucet - MultiStore storetypes.CommitMultiStore + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + CommunityPoolKeeper *MockCommunityPoolKeeper + EVMKeeper evmkeeper.Keeper + EncodingConfig EncodingConfig + Faucet *TestFaucet + MultiStore storetypes.CommitMultiStore } // createDefaultTestInput common settings for createTestInput func createDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) { - return createTestInput(t, false) + return createTestInput(t, false, true) } // createTestInput encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) -func createTestInput(t testing.TB, isCheckTx bool) (sdk.Context, TestKeepers) { +func createTestInput(t testing.TB, isCheckTx, initialize bool) (sdk.Context, TestKeepers) { // Load default move config - return _createTestInput(t, isCheckTx, dbm.NewMemDB()) + return _createTestInput(t, isCheckTx, initialize, dbm.NewMemDB()) } var keyCounter uint64 @@ -201,7 +197,7 @@ func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { // encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) func _createTestInput( t testing.TB, - isCheckTx bool, + isCheckTx, initialize bool, db dbm.DB, ) (sdk.Context, TestKeepers) { keys := storetypes.NewKVStoreKeys( @@ -228,18 +224,13 @@ func _createTestInput( appCodec := encodingConfig.Codec maccPerms := map[string][]string{ // module account permissions - authtypes.FeeCollectorName: nil, - distributiontypes.ModuleName: nil, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + authtypes.FeeCollectorName: nil, // for testing authtypes.Minter: {authtypes.Minter, authtypes.Burner}, } ac := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) - vc := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()) - cc := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()) accountKeeper := authkeeper.NewAccountKeeper( appCodec, @@ -265,54 +256,44 @@ func _createTestInput( ) require.NoError(t, bankKeeper.SetParams(ctx, banktypes.DefaultParams())) - stakingKeeper := stakingkeeper.NewKeeper( - appCodec, - runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), - accountKeeper, - bankKeeper, - authtypes.NewModuleAddress(govtypes.ModuleName).String(), - vc, cc, - ) - stakingParams := stakingtypes.DefaultParams() - require.NoError(t, stakingKeeper.SetParams(ctx, stakingParams)) - - distrKeeper := distributionkeeper.NewKeeper( - appCodec, - runtime.NewKVStoreService(keys[distributiontypes.StoreKey]), - accountKeeper, - bankKeeper, - stakingKeeper, - authtypes.FeeCollectorName, - authtypes.NewModuleAddress(govtypes.ModuleName).String(), - ) - distrParams := distributiontypes.DefaultParams() - require.NoError(t, distrKeeper.Params.Set(ctx, distrParams)) - stakingKeeper.SetHooks(distrKeeper.Hooks()) - - // set genesis items required for distribution - require.NoError(t, distrKeeper.FeePool.Set(ctx, distributiontypes.InitialFeePool())) - + communityPoolKeeper := &MockCommunityPoolKeeper{} evmKeeper := evmkeeper.NewKeeper( ac, appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), + accountKeeper, + communityPoolKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(), EVMConfig.DefaultEVMConfig(), ) evmParams := evmtypes.DefaultParams() require.NoError(t, evmKeeper.Params.Set(ctx, evmParams)) + if initialize { + require.NoError(t, evmKeeper.Initialize(ctx)) + } faucet := NewTestFaucet(t, ctx, bankKeeper, authtypes.Minter, initialTotalSupply()...) keepers := TestKeepers{ - AccountKeeper: accountKeeper, - StakingKeeper: *stakingKeeper, - DistKeeper: distrKeeper, - EVMKeeper: *evmKeeper, - BankKeeper: bankKeeper, - EncodingConfig: encodingConfig, - Faucet: faucet, - MultiStore: ms, + AccountKeeper: accountKeeper, + CommunityPoolKeeper: communityPoolKeeper, + EVMKeeper: *evmKeeper, + BankKeeper: bankKeeper, + EncodingConfig: encodingConfig, + Faucet: faucet, + MultiStore: ms, } return ctx, keepers } + +var _ evmtypes.CommunityPoolKeeper = &MockCommunityPoolKeeper{} + +type MockCommunityPoolKeeper struct { + CommunityPool sdk.Coins +} + +func (k *MockCommunityPoolKeeper) FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error { + k.CommunityPool = k.CommunityPool.Add(amount...) + + return nil +} diff --git a/x/evm/keeper/context.go b/x/evm/keeper/context.go index 41c5e32..f72ec92 100644 --- a/x/evm/keeper/context.go +++ b/x/evm/keeper/context.go @@ -2,16 +2,22 @@ package keeper import ( "context" + "encoding/hex" "math" "math/big" + "strings" + + "github.com/holiman/uint256" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" coretypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/holiman/uint256" + "github.com/ethereum/go-ethereum/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/initia-labs/minievm/x/evm/contracts/factory" "github.com/initia-labs/minievm/x/evm/types" ) @@ -29,6 +35,11 @@ func (k Keeper) computeGasLimit(sdkCtx sdk.Context) uint64 { func (k Keeper) buildBlockContext(ctx context.Context) vm.BlockContext { sdkCtx := sdk.UnwrapSDKContext(ctx) + headerHash := sdkCtx.HeaderHash() + if len(headerHash) == 0 { + headerHash = make([]byte, 32) + } + return vm.BlockContext{ GasLimit: k.computeGasLimit(sdkCtx), BlockNumber: big.NewInt(sdkCtx.BlockHeight()), @@ -42,42 +53,79 @@ func (k Keeper) buildBlockContext(ctx context.Context) vm.BlockContext { BaseFee: nil, BlobBaseFee: nil, // put header hash to bypass isMerge check in evm - Random: (*common.Hash)(sdkCtx.HeaderHash()), + Random: (*common.Hash)(headerHash), } } -func (k Keeper) buildTxContext(ctx context.Context, sender sdk.AccAddress) vm.TxContext { +func (k Keeper) buildTxContext(_ context.Context, caller common.Address) vm.TxContext { return vm.TxContext{ - Origin: common.BytesToAddress(sender.Bytes()), + Origin: caller, BlobFeeCap: nil, BlobHashes: nil, GasPrice: nil, } } -func (k Keeper) createEVM(ctx context.Context, sender sdk.AccAddress) (*vm.EVM, error) { +func (k Keeper) createEVM(ctx context.Context, caller common.Address) (*vm.EVM, error) { extraEIPs, err := k.ExtraEIPs(ctx) if err != nil { return nil, err } blockContext := k.buildBlockContext(ctx) - txContext := k.buildTxContext(ctx, sender) + txContext := k.buildTxContext(ctx, caller) stateDB, err := k.newStateDB(ctx) if err != nil { return nil, err } - return vm.NewEVM(blockContext, txContext, stateDB, types.DefaultChainConfig(), vm.Config{ExtraEips: extraEIPs}), nil + return vm.NewEVMWithPrecompiles( + blockContext, + txContext, + stateDB, + types.DefaultChainConfig(), + vm.Config{ExtraEips: extraEIPs}, + // vm.Config{ExtraEips: extraEIPs, + // Tracer: logger.NewJSONLogger(&logger.Config{ + // EnableMemory: false, + // DisableStack: true, + // DisableStorage: true, + // EnableReturnData: true, + // }, os.Stderr), + // }, + k.precompiles.toMap(ctx), + ), nil } -func (k Keeper) EVMCall(ctx context.Context, sender sdk.AccAddress, contractAddr common.Address, inputBz []byte) ([]byte, types.Logs, error) { - if len(sender) != common.AddressLength { - return nil, nil, types.ErrInvalidAddressLength +func (k Keeper) EVMStaticCall(ctx context.Context, caller common.Address, contractAddr common.Address, inputBz []byte) ([]byte, error) { + evm, err := k.createEVM(ctx, caller) + if err != nil { + return nil, err + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + gasBalance := k.computeGasLimit(sdkCtx) + + retBz, gasRemaining, err := evm.StaticCall( + vm.AccountRef(caller), + contractAddr, + inputBz, + gasBalance, + ) + + // London enforced + gasUsed := types.CalGasUsed(gasBalance, gasRemaining, evm.StateDB.GetRefund()) + sdkCtx.GasMeter().ConsumeGas(gasUsed, "EVM gas consumption") + if err != nil { + return nil, types.ErrEVMCallFailed.Wrap(err.Error()) } - evm, err := k.createEVM(ctx, sender) + return retBz, nil +} + +func (k Keeper) EVMCall(ctx context.Context, caller common.Address, contractAddr common.Address, inputBz []byte) ([]byte, types.Logs, error) { + evm, err := k.createEVM(ctx, caller) if err != nil { return nil, nil, err } @@ -86,7 +134,7 @@ func (k Keeper) EVMCall(ctx context.Context, sender sdk.AccAddress, contractAddr gasBalance := k.computeGasLimit(sdkCtx) retBz, gasRemaining, err := evm.Call( - vm.AccountRef(common.BytesToAddress(sender)), + vm.AccountRef(caller), contractAddr, inputBz, gasBalance, @@ -97,7 +145,7 @@ func (k Keeper) EVMCall(ctx context.Context, sender sdk.AccAddress, contractAddr gasUsed := types.CalGasUsed(gasBalance, gasRemaining, evm.StateDB.GetRefund()) sdkCtx.GasMeter().ConsumeGas(gasUsed, "EVM gas consumption") if err != nil { - return nil, nil, err + return nil, nil, types.ErrEVMCallFailed.Wrap(err.Error()) } // commit state transition @@ -120,16 +168,32 @@ func (k Keeper) EVMCall(ctx context.Context, sender sdk.AccAddress, contractAddr return nil, nil, err } + retHex := common.Bytes2Hex(retBz) logs := types.NewLogs(stateDB.Logs()) - return retBz, logs, nil -} -func (k Keeper) EVMCreate(ctx context.Context, sender sdk.AccAddress, codeBz []byte) ([]byte, common.Address, error) { - if len(sender) != common.AddressLength { - return nil, common.Address{}, types.ErrInvalidAddressLength + // emit action events + sdkCtx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeCall, + sdk.NewAttribute(types.AttributeKeyContract, contractAddr.Hex()), + sdk.NewAttribute(types.AttributeKeyRet, retHex), + )) + + // emit logs events + for _, log := range logs { + for _, topic := range log.Topics { + sdkCtx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeLog, + sdk.NewAttribute(types.AttributeKeyTopic, topic), + sdk.NewAttribute(types.AttributeKeyRet, log.Data), + )) + } } - evm, err := k.createEVM(ctx, sender) + return retBz, logs, nil +} + +func (k Keeper) EVMCreate(ctx context.Context, caller common.Address, codeBz []byte) ([]byte, common.Address, error) { + evm, err := k.createEVM(ctx, caller) if err != nil { return nil, common.Address{}, err } @@ -137,7 +201,7 @@ func (k Keeper) EVMCreate(ctx context.Context, sender sdk.AccAddress, codeBz []b sdkCtx := sdk.UnwrapSDKContext(ctx) gasBalance := k.computeGasLimit(sdkCtx) retBz, contractAddr, gasRemaining, err := evm.Create( - vm.AccountRef(common.BytesToAddress(sender)), + vm.AccountRef(caller), codeBz, gasBalance, uint256.NewInt(0), @@ -147,7 +211,7 @@ func (k Keeper) EVMCreate(ctx context.Context, sender sdk.AccAddress, codeBz []b gasUsed := types.CalGasUsed(gasBalance, gasRemaining, evm.StateDB.GetRefund()) sdkCtx.GasMeter().ConsumeGas(gasUsed, "EVM gas consumption") if err != nil { - return nil, common.Address{}, err + return nil, common.Address{}, types.ErrEVMCreateFailed.Wrap(err.Error()) } // commit state transition @@ -170,5 +234,37 @@ func (k Keeper) EVMCreate(ctx context.Context, sender sdk.AccAddress, codeBz []b return nil, common.Address{}, err } + retHex := common.Bytes2Hex(retBz) + + // emit action events + sdkCtx.EventManager().EmitEvent(sdk.NewEvent( + types.EventTypeCall, + sdk.NewAttribute(types.AttributeKeyContract, contractAddr.Hex()), + sdk.NewAttribute(types.AttributeKeyRet, retHex), + )) + return retBz, contractAddr, nil } + +func (k Keeper) Initialize(ctx context.Context) error { + bin, err := hex.DecodeString(strings.TrimPrefix(factory.FactoryBin, "0x")) + if err != nil { + return err + } + + _, _, err = k.EVMCreate(ctx, types.StdAddress, bin) + if err != nil { + return err + } + + return nil +} + +func (k Keeper) NextContractAddress(ctx context.Context, caller common.Address) (common.Address, error) { + stateDB, err := k.newStateDB(ctx) + if err != nil { + return common.Address{}, err + } + + return crypto.CreateAddress(caller, stateDB.GetNonce(caller)), nil +} diff --git a/x/evm/keeper/context_test.go b/x/evm/keeper/context_test.go index 2abd45d..3e36d7a 100644 --- a/x/evm/keeper/context_test.go +++ b/x/evm/keeper/context_test.go @@ -5,8 +5,12 @@ import ( "strings" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" "github.com/holiman/uint256" "github.com/initia-labs/minievm/x/evm/contracts/counter" + "github.com/initia-labs/minievm/x/evm/contracts/erc20" + "github.com/stretchr/testify/require" ) @@ -17,7 +21,8 @@ func Test_Create(t *testing.T) { counterBz, err := hex.DecodeString(strings.TrimPrefix(counter.CounterBin, "0x")) require.NoError(t, err) - retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, addr, counterBz) + caller := common.BytesToAddress(addr.Bytes()) + retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, caller, counterBz) require.NoError(t, err) require.NotEmpty(t, retBz) require.Len(t, contractAddr, 20) @@ -30,7 +35,8 @@ func Test_Call(t *testing.T) { counterBz, err := hex.DecodeString(strings.TrimPrefix(counter.CounterBin, "0x")) require.NoError(t, err) - retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, addr, counterBz) + caller := common.BytesToAddress(addr.Bytes()) + retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, caller, counterBz) require.NoError(t, err) require.NotEmpty(t, retBz) require.Len(t, contractAddr, 20) @@ -41,7 +47,7 @@ func Test_Call(t *testing.T) { queryInputBz, err := parsed.Pack("count") require.NoError(t, err) - queryRes, logs, err := input.EVMKeeper.EVMCall(ctx, addr, contractAddr, queryInputBz) + queryRes, logs, err := input.EVMKeeper.EVMCall(ctx, caller, contractAddr, queryInputBz) require.NoError(t, err) require.Equal(t, uint256.NewInt(0).Bytes32(), [32]byte(queryRes)) require.Empty(t, logs) @@ -49,13 +55,23 @@ func Test_Call(t *testing.T) { inputBz, err := parsed.Pack("increase") require.NoError(t, err) - res, logs, err := input.EVMKeeper.EVMCall(ctx, addr, contractAddr, inputBz) + res, logs, err := input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz) require.NoError(t, err) require.Empty(t, res) require.NotEmpty(t, logs) - queryRes, logs, err = input.EVMKeeper.EVMCall(ctx, addr, contractAddr, queryInputBz) + queryRes, logs, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, queryInputBz) require.NoError(t, err) require.Equal(t, uint256.NewInt(1).Bytes32(), [32]byte(queryRes)) require.Empty(t, logs) + + // calling not existing function + erc20ABI, err := erc20.Erc20MetaData.GetAbi() + require.NoError(t, err) + + queryInputBz, err = erc20ABI.Pack("balanceOf", caller) + require.NoError(t, err) + + _, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, queryInputBz) + require.ErrorContains(t, err, vm.ErrExecutionReverted.Error()) } diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go new file mode 100644 index 0000000..2e68de7 --- /dev/null +++ b/x/evm/keeper/erc20.go @@ -0,0 +1,495 @@ +package keeper + +import ( + "context" + "encoding/hex" + "math/big" + "strings" + + "cosmossdk.io/collections" + moderrors "cosmossdk.io/errors" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/initia-labs/minievm/x/evm/contracts/erc20" + "github.com/initia-labs/minievm/x/evm/contracts/factory" + "github.com/initia-labs/minievm/x/evm/types" +) + +type ERC20Keeper struct { + *Keeper + *abi.ABI + FactoryABI *abi.ABI + ERC20Bin []byte +} + +func NewERC20Keeper(k *Keeper) (types.IERC20Keeper, error) { + abi, err := erc20.Erc20MetaData.GetAbi() + if err != nil { + return ERC20Keeper{}, err + } + + factoryABI, err := factory.FactoryMetaData.GetAbi() + if err != nil { + return ERC20Keeper{}, err + } + + erc20Bin, err := hex.DecodeString(strings.TrimPrefix(erc20.Erc20Bin, "0x")) + if err != nil { + return ERC20Keeper{}, err + } + + return &ERC20Keeper{k, abi, factoryABI, erc20Bin}, nil +} + +// BurnCoins implements IERC20Keeper. +func (k ERC20Keeper) BurnCoins(ctx context.Context, addr sdk.AccAddress, amount sdk.Coins) error { + if len(addr.Bytes()) != common.AddressLength { + return types.ErrInvalidAddressLength + } + + evmAddr := common.BytesToAddress(addr.Bytes()) + for _, coin := range amount { + // if a coin is not generated from 0x1, then send the coin to community pool + // because we don't have burn capability. + if types.IsERC20Denom(coin.Denom) { + if err := k.communityPoolKeeper.FundCommunityPool(ctx, amount, evmAddr.Bytes()); err != nil { + return err + } + + continue + } + + // burn coins + contractAddr, err := types.DenomToContractAddr(ctx, k, coin.Denom) + if err != nil { + return err + } + + inputBz, err := k.ABI.Pack("burn", evmAddr, coin.Amount.BigInt()) + if err != nil { + return types.ErrFailedToPackABI.Wrap(err.Error()) + } + + // ignore the return values + _, _, err = k.EVMCall(ctx, types.StdAddress, contractAddr, inputBz) + if err != nil { + return err + } + } + + return nil +} + +// GetBalance implements IERC20Keeper. +func (k ERC20Keeper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) (math.Int, error) { + if len(addr.Bytes()) != common.AddressLength { + return math.ZeroInt(), types.ErrInvalidAddressLength + } + + evmAddr := common.BytesToAddress(addr.Bytes()) + contractAddr, err := types.DenomToContractAddr(ctx, k, denom) + if err != nil { + return math.ZeroInt(), err + } + + return k.balanceOf( + ctx, + evmAddr, + contractAddr, + ) +} + +// GetMetadata implements IERC20Keeper. +func (k ERC20Keeper) GetMetadata(ctx context.Context, denom string) (banktypes.Metadata, error) { + contractAddr, err := types.DenomToContractAddr(ctx, k, denom) + if err != nil { + return banktypes.Metadata{}, err + } + + name, err := k.name(ctx, contractAddr) + if err != nil { + return banktypes.Metadata{}, err + } + + symbol, err := k.symbol(ctx, contractAddr) + if err != nil { + return banktypes.Metadata{}, err + } + + decimals, err := k.decimals(ctx, contractAddr) + if err != nil { + return banktypes.Metadata{}, err + } + + denomUnits := []*banktypes.DenomUnit{ + { + Denom: denom, + Exponent: 0, + }, + } + + base := denom + display := denom + if decimals == 0 { + if !strings.Contains(denom, "/") && denom[0] == 'u' { + display = denom[1:] + denomUnits = append(denomUnits, &banktypes.DenomUnit{ + Denom: display, + Exponent: 6, + }) + } else if !strings.Contains(denom, "/") && denom[0] == 'm' { + display = denom[1:] + denomUnits = append(denomUnits, &banktypes.DenomUnit{ + Denom: display, + Exponent: 3, + }) + } + } + + return banktypes.Metadata{ + Name: name, + Symbol: symbol, + Base: base, + Display: display, + DenomUnits: denomUnits, + }, nil +} + +// GetPaginatedBalances implements IERC20Keeper. +func (k ERC20Keeper) GetPaginatedBalances(ctx context.Context, pageReq *query.PageRequest, addr sdk.AccAddress) (sdk.Coins, *query.PageResponse, error) { + if len(addr.Bytes()) != common.AddressLength { + return nil, nil, types.ErrInvalidAddressLength + } + + evmAddr := common.BytesToAddress(addr.Bytes()) + coins, res, err := query.CollectionPaginate(ctx, k.ERC20Stores, pageReq, func(key collections.Pair[[]byte, []byte], _ collections.NoValue) (sdk.Coin, error) { + balance, err := k.balanceOf(ctx, common.BytesToAddress(key.K1()), common.BytesToAddress(key.K2())) + if err != nil { + balance = math.ZeroInt() + } + + denom, err := types.ContractAddrToDenom(ctx, k, common.BytesToAddress(key.K2())) + if err != nil { + balance = math.ZeroInt() + } + + return sdk.NewCoin(denom, balance), nil + }, func(opt *query.CollectionsPaginateOptions[collections.Pair[[]byte, []byte]]) { + prefix := collections.PairPrefix[[]byte, []byte](evmAddr.Bytes()) + opt.Prefix = &prefix + }) + + return sdk.Coins(coins).Sort(), res, err +} + +// GetPaginatedSupply implements IERC20Keeper. +func (k ERC20Keeper) GetPaginatedSupply(ctx context.Context, pageReq *query.PageRequest) (sdk.Coins, *query.PageResponse, error) { + coins, res, err := query.CollectionPaginate(ctx, k.ERC20s, pageReq, func(contractAddr []byte, _ collections.NoValue) (sdk.Coin, error) { + supply, err := k.totalSupply(ctx, common.BytesToAddress(contractAddr)) + if err != nil { + supply = math.ZeroInt() + } + + denom, err := types.ContractAddrToDenom(ctx, k, common.BytesToAddress(contractAddr)) + if err != nil { + supply = math.ZeroInt() + } + + return sdk.NewCoin(denom, supply), nil + }) + + return sdk.Coins(coins).Sort(), res, err +} + +// GetSupply implements IERC20Keeper. +func (k ERC20Keeper) GetSupply(ctx context.Context, denom string) (math.Int, error) { + contractAddr, err := types.DenomToContractAddr(ctx, k, denom) + if err != nil { + return math.ZeroInt(), err + } + + return k.totalSupply(ctx, contractAddr) +} + +// HasSupply implements IERC20Keeper. +func (k ERC20Keeper) HasSupply(ctx context.Context, denom string) (bool, error) { + contractAddr, err := types.DenomToContractAddr(ctx, k, denom) + if err != nil { + return false, err + } + + return k.ERC20s.Has(ctx, contractAddr.Bytes()) +} + +// IterateAccountBalances implements IERC20Keeper. +func (k ERC20Keeper) IterateAccountBalances(ctx context.Context, addr sdk.AccAddress, cb func(sdk.Coin) (bool, error)) error { + if len(addr.Bytes()) != common.AddressLength { + return types.ErrInvalidAddressLength + } + + evmAddr := common.BytesToAddress(addr.Bytes()) + return k.ERC20Stores.Walk(ctx, collections.NewPrefixedPairRange[[]byte, []byte](evmAddr.Bytes()), func(key collections.Pair[[]byte, []byte]) (stop bool, err error) { + balance, err := k.balanceOf(ctx, common.BytesToAddress(key.K1()), common.BytesToAddress(key.K2())) + if err != nil { + balance = math.ZeroInt() + } + + denom, err := types.ContractAddrToDenom(ctx, k, common.BytesToAddress(key.K2())) + if err != nil { + balance = math.ZeroInt() + } + + // not return zero balance + if balance.IsZero() { + return false, nil + } + + return cb(sdk.NewCoin(denom, balance)) + }) +} + +// IterateSupply implements IERC20Keeper. +func (k ERC20Keeper) IterateSupply(ctx context.Context, cb func(supply sdk.Coin) (bool, error)) error { + return k.ERC20s.Walk(ctx, nil, func(contractAddr []byte) (stop bool, err error) { + supply, err := k.totalSupply(ctx, common.BytesToAddress(contractAddr)) + if err != nil { + supply = math.ZeroInt() + } + + denom, err := types.ContractAddrToDenom(ctx, k, common.BytesToAddress(contractAddr)) + if err != nil { + supply = math.ZeroInt() + } + + return cb(sdk.NewCoin(denom, supply)) + }) +} + +// MintCoins implements IERC20Keeper. +func (k ERC20Keeper) MintCoins(ctx context.Context, addr sdk.AccAddress, amount sdk.Coins) error { + if len(addr.Bytes()) != common.AddressLength { + return types.ErrInvalidAddressLength + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + evmAddr := common.BytesToAddress(addr.Bytes()) + + for _, coin := range amount { + denom := coin.Denom + if types.IsERC20Denom(denom) { + return moderrors.Wrapf(types.ErrInvalidRequest, "cannot mint erc20 coin: %s", coin.Denom) + } + + // check whether the erc20 contract exists or not and create it if not + if found, err := k.ERC20ContractAddrsByDenom.Has(ctx, denom); err != nil { + return err + } else if !found { + inputBz, err := k.FactoryABI.Pack("deployNewERC20", denom, denom, uint8(0)) + if err != nil { + return types.ErrFailedToPackABI.Wrap(err.Error()) + } + + factoryAddr := types.FactoryAddress() + contractAddr, err := k.NextContractAddress(ctx, factoryAddr) + if err != nil { + return err + } + + if err := k.ERC20DenomsByContractAddr.Set(ctx, contractAddr.Bytes(), denom); err != nil { + return err + } + + if err := k.ERC20ContractAddrsByDenom.Set(ctx, denom, contractAddr.Bytes()); err != nil { + return err + } + + ret, _, err := k.EVMCall(ctx, types.StdAddress, factoryAddr, inputBz) + if err != nil { + return err + } + + // emit erc20 created event + sdkCtx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeERC20Created, + sdk.NewAttribute(types.AttributeKeyDenom, denom), + sdk.NewAttribute(types.AttributeKeyContract, common.Bytes2Hex(ret)), + ), + ) + } + + // mint coin + contractAddr, err := types.DenomToContractAddr(ctx, k, denom) + if err != nil { + return err + } + + inputBz, err := k.ABI.Pack("mint", evmAddr, coin.Amount.BigInt()) + if err != nil { + return types.ErrFailedToPackABI.Wrap(err.Error()) + } + + // ignore the return values + _, _, err = k.EVMCall(ctx, types.StdAddress, contractAddr, inputBz) + if err != nil { + return err + } + } + + return nil +} + +// SendCoins implements IERC20Keeper. +func (k ERC20Keeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { + if len(fromAddr.Bytes()) != 20 || len(toAddr.Bytes()) != 20 { + return types.ErrInvalidAddressLength + } + + evmFromAddr := common.BytesToAddress(fromAddr.Bytes()) + evmToAddr := common.BytesToAddress(toAddr.Bytes()) + for _, coin := range amt { + contractAddr, err := types.DenomToContractAddr(ctx, k, coin.Denom) + if err != nil { + return err + } + + inputBz, err := k.ABI.Pack("transfer", evmToAddr, coin.Amount.BigInt()) + if err != nil { + return types.ErrFailedToPackABI.Wrap(err.Error()) + } + + // ignore the return values + _, _, err = k.EVMCall(ctx, evmFromAddr, contractAddr, inputBz) + if err != nil { + return err + } + } + + return nil +} + +func (k ERC20Keeper) balanceOf(ctx context.Context, addr, contractAddr common.Address) (math.Int, error) { + inputBz, err := k.ABI.Pack("balanceOf", addr) + if err != nil { + return math.ZeroInt(), types.ErrFailedToPackABI.Wrap(err.Error()) + } + + retBz, err := k.EVMStaticCall(ctx, types.NullAddress, contractAddr, inputBz) + if err != nil { + return math.ZeroInt(), err + } + + res, err := k.ABI.Unpack("balanceOf", retBz) + if err != nil { + return math.ZeroInt(), types.ErrFailedToUnpackABI.Wrap(err.Error()) + } + + balance, ok := res[0].(*big.Int) + if !ok { + return math.ZeroInt(), types.ErrFailedToDecodeOutput + } + + return math.NewIntFromBigInt(balance), nil +} + +func (k ERC20Keeper) totalSupply(ctx context.Context, contractAddr common.Address) (math.Int, error) { + inputBz, err := k.ABI.Pack("totalSupply") + if err != nil { + return math.ZeroInt(), types.ErrFailedToPackABI.Wrap(err.Error()) + } + + retBz, err := k.EVMStaticCall(ctx, types.NullAddress, contractAddr, inputBz) + if err != nil { + return math.ZeroInt(), err + } + + res, err := k.ABI.Unpack("totalSupply", retBz) + if err != nil { + return math.ZeroInt(), types.ErrFailedToUnpackABI.Wrap(err.Error()) + } + + totalSupply, ok := res[0].(*big.Int) + if !ok { + return math.ZeroInt(), types.ErrFailedToDecodeOutput + } + + return math.NewIntFromBigInt(totalSupply), nil +} + +func (k ERC20Keeper) name(ctx context.Context, contractAddr common.Address) (string, error) { + inputBz, err := k.ABI.Pack("name") + if err != nil { + return "", types.ErrFailedToPackABI.Wrap(err.Error()) + } + + retBz, err := k.EVMStaticCall(ctx, types.NullAddress, contractAddr, inputBz) + if err != nil { + return "", err + } + + res, err := k.ABI.Unpack("name", retBz) + if err != nil { + return "", types.ErrFailedToUnpackABI.Wrap(err.Error()) + } + + name, ok := res[0].(string) + if !ok { + return name, types.ErrFailedToDecodeOutput + } + + return name, nil +} + +func (k ERC20Keeper) symbol(ctx context.Context, contractAddr common.Address) (string, error) { + inputBz, err := k.ABI.Pack("symbol") + if err != nil { + return "", types.ErrFailedToPackABI.Wrap(err.Error()) + } + + retBz, err := k.EVMStaticCall(ctx, types.NullAddress, contractAddr, inputBz) + if err != nil { + return "", err + } + + res, err := k.ABI.Unpack("symbol", retBz) + if err != nil { + return "", types.ErrFailedToUnpackABI.Wrap(err.Error()) + } + + symbol, ok := res[0].(string) + if !ok { + return symbol, types.ErrFailedToDecodeOutput + } + + return symbol, nil +} + +func (k ERC20Keeper) decimals(ctx context.Context, contractAddr common.Address) (uint8, error) { + inputBz, err := k.ABI.Pack("decimals") + if err != nil { + return 0, types.ErrFailedToPackABI.Wrap(err.Error()) + } + + retBz, err := k.EVMStaticCall(ctx, types.NullAddress, contractAddr, inputBz) + if err != nil { + return 0, err + } + + res, err := k.ABI.Unpack("decimals", retBz) + if err != nil { + return 0, types.ErrFailedToUnpackABI.Wrap(err.Error()) + } + + decimals, ok := res[0].(uint8) + if !ok { + return decimals, types.ErrFailedToDecodeOutput + } + + return decimals, nil +} diff --git a/x/evm/keeper/erc20_stores.go b/x/evm/keeper/erc20_stores.go new file mode 100644 index 0000000..dfae3d1 --- /dev/null +++ b/x/evm/keeper/erc20_stores.go @@ -0,0 +1,70 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/collections" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + "github.com/initia-labs/minievm/x/evm/types" +) + +type ERC20StoresKeeper struct { + *Keeper +} + +func NewERC20StoresKeeper(k *Keeper) types.IERC20StoresKeeper { + return &ERC20StoresKeeper{k} +} + +func (k ERC20StoresKeeper) IsStoreRegistered(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) (bool, error) { + return k.ERC20Stores.Has(ctx, collections.Join(addr.Bytes(), contractAddr.Bytes())) +} + +func (k ERC20StoresKeeper) RegisterStore(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) error { + // create account if not exists + if !k.accountKeeper.HasAccount(ctx, addr) { + k.accountKeeper.SetAccount(ctx, k.accountKeeper.NewAccountWithAddress(ctx, addr)) + } + + return k.ERC20Stores.Set(ctx, collections.Join(addr.Bytes(), contractAddr.Bytes())) +} + +func (k ERC20StoresKeeper) Register(ctx context.Context, contractAddr common.Address) error { + if k.accountKeeper.HasAccount(ctx, sdk.AccAddress(contractAddr.Bytes())) { + account := k.accountKeeper.GetAccount(ctx, sdk.AccAddress(contractAddr.Bytes())) + if account.GetPubKey() != nil { + return types.ErrAddressAlreadyExists.Wrap(contractAddr.String()) + } + + // convert normal account to contract account + contractAccount := types.NewContractAccountWithAddress(contractAddr.Bytes()) + contractAccount.AccountNumber = account.GetAccountNumber() + k.accountKeeper.SetAccount(ctx, contractAccount) + } else { + // create contract account + contractAccount := types.NewContractAccountWithAddress(contractAddr.Bytes()) + contractAccount.AccountNumber = k.accountKeeper.NextAccountNumber(ctx) + k.accountKeeper.SetAccount(ctx, contractAccount) + } + + if found, err := k.ERC20DenomsByContractAddr.Has(ctx, contractAddr.Bytes()); err != nil { + return err + } else if !found { + // register denom and contract address conversion to the store + denom, err := types.ContractAddrToDenom(ctx, k, contractAddr) + if err != nil { + return err + } + + if err := k.ERC20DenomsByContractAddr.Set(ctx, contractAddr.Bytes(), denom); err != nil { + return err + } + + if err := k.ERC20ContractAddrsByDenom.Set(ctx, denom, contractAddr.Bytes()); err != nil { + return err + } + } + + return k.ERC20s.Set(ctx, contractAddr.Bytes()) +} diff --git a/x/evm/keeper/erc20_test.go b/x/evm/keeper/erc20_test.go new file mode 100644 index 0000000..3b8b404 --- /dev/null +++ b/x/evm/keeper/erc20_test.go @@ -0,0 +1,293 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/initia-labs/minievm/x/evm/contracts/erc20" + "github.com/initia-labs/minievm/x/evm/contracts/factory" + "github.com/initia-labs/minievm/x/evm/keeper" + "github.com/initia-labs/minievm/x/evm/types" +) + +func deployERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller common.Address, denom string) common.Address { + abi, err := factory.FactoryMetaData.GetAbi() + require.NoError(t, err) + + inputBz, err := abi.Pack("deployNewERC20", denom, denom, uint8(6)) + require.NoError(t, err) + + ret, _, err := input.EVMKeeper.EVMCall(ctx, caller, types.FactoryAddress(), inputBz) + require.NoError(t, err) + + contractAddr := common.BytesToAddress(ret) + return contractAddr +} + +func mintERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, recipient common.Address, amount sdk.Coin) { + abi, err := erc20.Erc20MetaData.GetAbi() + require.NoError(t, err) + + inputBz, err := abi.Pack("mint", recipient, amount.Amount.BigInt()) + require.NoError(t, err) + + erc20ContractAddr, err := types.DenomToContractAddr(ctx, &input.EVMKeeper, amount.Denom) + require.NoError(t, err) + + _, _, err = input.EVMKeeper.EVMCall(ctx, caller, erc20ContractAddr, inputBz) + require.NoError(t, err) +} + +func Test_MintBurn(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + + erc20Keeper, err := keeper.NewERC20Keeper(&input.EVMKeeper) + require.NoError(t, err) + + // deploy erc20 contract + fooContractAddr := deployERC20(t, ctx, input, evmAddr, "foo") + fooDenom, err := types.ContractAddrToDenom(ctx, &input.EVMKeeper, fooContractAddr) + require.NoError(t, err) + require.Equal(t, "evm/"+fooContractAddr.Hex()[2:], fooDenom) + + // cannot mint erc20 from cosmos side + cacheCtx, _ := ctx.CacheContext() + err = erc20Keeper.MintCoins(cacheCtx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + sdk.NewCoin(fooDenom, math.NewInt(100)), + )) + require.Error(t, err) + + // mint success + err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + )) + require.NoError(t, err) + + // mint erc20 + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100))) + + amount, err := erc20Keeper.GetBalance(ctx, addr, "bar") + require.NoError(t, err) + require.Equal(t, math.NewInt(200), amount) + + amount, err = erc20Keeper.GetBalance(ctx, addr, fooDenom) + require.NoError(t, err) + require.Equal(t, math.NewInt(100), amount) + + // erc20(foo) coins will be sent to community pool + err = erc20Keeper.BurnCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(50)), + sdk.NewCoin(fooDenom, math.NewInt(50)), + )) + require.NoError(t, err) + + res, _, err := erc20Keeper.GetPaginatedBalances(ctx, nil, addr) + require.NoError(t, err) + require.Equal(t, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(150)), + sdk.NewCoin(fooDenom, math.NewInt(100)), + ), res) + + // check community pool + require.Equal(t, math.NewInt(50), input.CommunityPoolKeeper.CommunityPool.AmountOf(fooDenom)) +} + +func Test_SendCoins(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + _, _, addr2 := keyPubAddr() + + erc20Keeper, err := keeper.NewERC20Keeper(&input.EVMKeeper) + require.NoError(t, err) + + err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + sdk.NewCoin("foo", math.NewInt(100)), + )) + require.NoError(t, err) + + err = erc20Keeper.SendCoins(ctx, addr, addr2, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(100)), + sdk.NewCoin("foo", math.NewInt(50)), + )) + require.NoError(t, err) + + res, _, err := erc20Keeper.GetPaginatedBalances(ctx, nil, addr) + require.NoError(t, err) + require.Equal(t, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(100)), + sdk.NewCoin("foo", math.NewInt(50)), + ), res) + + res2, _, err := erc20Keeper.GetPaginatedBalances(ctx, nil, addr2) + require.NoError(t, err) + require.Equal(t, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(100)), + sdk.NewCoin("foo", math.NewInt(50)), + ), res2) +} + +func Test_GetSupply(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + _, _, addr2 := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + + erc20Keeper, err := keeper.NewERC20Keeper(&input.EVMKeeper) + require.NoError(t, err) + + // deploy erc20 contract + fooContractAddr := deployERC20(t, ctx, input, evmAddr, "foo") + fooDenom, err := types.ContractAddrToDenom(ctx, &input.EVMKeeper, fooContractAddr) + require.NoError(t, err) + require.Equal(t, "evm/"+fooContractAddr.Hex()[2:], fooDenom) + + // mint erc20 + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100))) + + // mint native coin + err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + )) + require.NoError(t, err) + + err = erc20Keeper.SendCoins(ctx, addr, addr2, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(100)), + sdk.NewCoin(fooDenom, math.NewInt(50)), + )) + require.NoError(t, err) + + amount, err := erc20Keeper.GetSupply(ctx, fooDenom) + require.NoError(t, err) + require.Equal(t, math.NewInt(100), amount) + + has, err := erc20Keeper.HasSupply(ctx, fooDenom) + require.NoError(t, err) + require.True(t, has) + + amount, err = erc20Keeper.GetSupply(ctx, "bar") + require.NoError(t, err) + require.Equal(t, math.NewInt(200), amount) + + has, err = erc20Keeper.HasSupply(ctx, "bar") + require.NoError(t, err) + require.True(t, has) + + erc20Keeper.IterateSupply(ctx, func(supply sdk.Coin) (bool, error) { + require.True(t, supply.Denom == "bar" || supply.Denom == fooDenom) + switch supply.Denom { + case "bar": + require.Equal(t, math.NewInt(200), supply.Amount) + case fooDenom: + require.Equal(t, math.NewInt(100), supply.Amount) + } + return false, nil + }) + + supply, _, err := erc20Keeper.GetPaginatedSupply(ctx, nil) + require.NoError(t, err) + require.Equal(t, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + sdk.NewCoin(fooDenom, math.NewInt(100)), + ), supply) +} + +func TestERC20Keeper_GetMetadata(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + + erc20Keeper, err := keeper.NewERC20Keeper(&input.EVMKeeper) + require.NoError(t, err) + + err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + sdk.NewCoin("foo", math.NewInt(100)), + )) + require.NoError(t, err) + + supply, err := erc20Keeper.GetSupply(ctx, "foo") + require.NoError(t, err) + require.Equal(t, math.NewInt(100), supply) + + metadata, err := erc20Keeper.GetMetadata(ctx, "foo") + require.NoError(t, err) + + require.Equal(t, banktypes.Metadata{ + Description: "", + Base: "foo", + Display: "foo", + Name: "foo", + Symbol: "foo", + URI: "", + URIHash: "", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "foo", + Exponent: 0, + }, + }, + }, metadata) +} + +func Test_IterateAccountBalances(t *testing.T) { + ctx, input := createDefaultTestInput(t) + _, _, addr := keyPubAddr() + _, _, addr2 := keyPubAddr() + + evmAddr := common.BytesToAddress(addr.Bytes()) + evmAddr2 := common.BytesToAddress(addr2.Bytes()) + + erc20Keeper, err := keeper.NewERC20Keeper(&input.EVMKeeper) + require.NoError(t, err) + + // deploy erc20 contract + fooContractAddr := deployERC20(t, ctx, input, evmAddr, "foo") + fooDenom, err := types.ContractAddrToDenom(ctx, &input.EVMKeeper, fooContractAddr) + require.NoError(t, err) + require.Equal(t, "evm/"+fooContractAddr.Hex()[2:], fooDenom) + + // mint erc20 + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100))) + mintERC20(t, ctx, input, evmAddr, evmAddr2, sdk.NewCoin(fooDenom, math.NewInt(200))) + + // mint native coin + err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(200)), + )) + require.NoError(t, err) + err = erc20Keeper.MintCoins(ctx, addr2, sdk.NewCoins( + sdk.NewCoin("bar", math.NewInt(400)), + )) + require.NoError(t, err) + + erc20Keeper.IterateAccountBalances(ctx, addr, func(balance sdk.Coin) (bool, error) { + require.True(t, balance.Denom == "bar" || balance.Denom == fooDenom) + switch balance.Denom { + case "bar": + require.Equal(t, math.NewInt(200), balance.Amount) + case fooDenom: + require.Equal(t, math.NewInt(100), balance.Amount) + } + return false, nil + }) + + erc20Keeper.IterateAccountBalances(ctx, addr2, func(balance sdk.Coin) (bool, error) { + require.True(t, balance.Denom == "bar" || balance.Denom == fooDenom) + switch balance.Denom { + case "bar": + require.Equal(t, math.NewInt(400), balance.Amount) + case fooDenom: + require.Equal(t, math.NewInt(200), balance.Amount) + } + return false, nil + }) +} diff --git a/x/evm/keeper/genesis.go b/x/evm/keeper/genesis.go index c500742..cbcfedf 100644 --- a/x/evm/keeper/genesis.go +++ b/x/evm/keeper/genesis.go @@ -1,8 +1,10 @@ package keeper import ( + "bytes" "context" + "cosmossdk.io/collections" "github.com/initia-labs/minievm/x/evm/types" ) @@ -11,6 +13,12 @@ func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) er return err } + // if the genesis is not exported, initialize the state + if !genState.IsExported() { + return k.Initialize(ctx) + } + + // else set the state from the genesis if err := k.VMRoot.Set(ctx, genState.StateRoot); err != nil { return err } @@ -21,6 +29,24 @@ func (k Keeper) InitGenesis(ctx context.Context, genState types.GenesisState) er } } + for _, stores := range genState.Erc20Stores { + for _, store := range stores.Stores { + if err := k.ERC20Stores.Set(ctx, collections.Join(stores.Address, store)); err != nil { + return err + } + } + } + + for _, denomAddress := range genState.DenomAddresses { + if err := k.ERC20ContractAddrsByDenom.Set(ctx, denomAddress.Denom, denomAddress.ContractAddress); err != nil { + return err + } + + if err := k.ERC20DenomsByContractAddr.Set(ctx, denomAddress.ContractAddress, denomAddress.Denom); err != nil { + return err + } + } + return nil } @@ -41,9 +67,38 @@ func (k Keeper) ExportGenesis(ctx context.Context) *types.GenesisState { return false, nil }) + var stores *types.GenesisERC20Stores + erc20Stores := []types.GenesisERC20Stores{} + k.ERC20Stores.Walk(ctx, nil, func(key collections.Pair[[]byte, []byte]) (stop bool, err error) { + if stores == nil || !bytes.Equal(stores.Address, key.K1()) { + erc20Stores = append(erc20Stores, types.GenesisERC20Stores{ + Address: key.K1(), + Stores: [][]byte{key.K2()}, + }) + + stores = &erc20Stores[len(erc20Stores)-1] + return false, nil + } + + stores.Stores = append(stores.Stores, key.K2()) + return false, nil + }) + + denomAddresses := []types.GenesisDenomAddress{} + k.ERC20ContractAddrsByDenom.Walk(ctx, nil, func(denom string, contractAddr []byte) (stop bool, err error) { + denomAddresses = append(denomAddresses, types.GenesisDenomAddress{ + Denom: denom, + ContractAddress: contractAddr, + }) + + return false, nil + }) + return &types.GenesisState{ - Params: params, - StateRoot: stateRoot, - KeyValues: kvs, + Params: params, + StateRoot: stateRoot, + KeyValues: kvs, + Erc20Stores: erc20Stores, + DenomAddresses: denomAddresses, } } diff --git a/x/evm/keeper/genesis_test.go b/x/evm/keeper/genesis_test.go new file mode 100644 index 0000000..84eae07 --- /dev/null +++ b/x/evm/keeper/genesis_test.go @@ -0,0 +1,54 @@ +package keeper_test + +import ( + "testing" + + "github.com/initia-labs/minievm/x/evm/types" + "github.com/stretchr/testify/require" +) + +func Test_Genesis(t *testing.T) { + ctx, input := createTestInput(t, false, false) + + genState := types.DefaultGenesis() + genState.StateRoot = []byte{1, 2, 3, 4} + genState.Erc20Stores = []types.GenesisERC20Stores{ + { + Address: []byte{1, 2, 3}, + Stores: [][]byte{{1, 2, 3, 4, 5, 6, 7}, {8, 9, 1, 2, 3, 4}}, + }, + { + Address: []byte{4, 2, 3}, + Stores: [][]byte{{1, 2, 3, 4, 5, 6, 7}, {8, 9, 1, 2, 3, 4}}, + }, + } + genState.KeyValues = []types.GenesisKeyValue{ + { + Key: []byte{1, 2, 3, 4}, + Value: []byte{1, 2, 3, 5, 32}, + }, + { + Key: []byte{5, 6, 7, 8}, + Value: []byte{1, 2, 3, 1, 32}, + }, + { + Key: []byte{9, 10, 11, 12, 13}, + Value: []byte{1, 2, 3, 5, 32, 4}, + }, + } + genState.DenomAddresses = []types.GenesisDenomAddress{ + { + Denom: "denom1", + ContractAddress: []byte{1, 2, 3, 4, 5, 6, 7}, + }, + { + Denom: "denom2", + ContractAddress: []byte{8, 9, 1, 2, 3, 4}, + }, + } + err := input.EVMKeeper.InitGenesis(ctx, *genState) + require.NoError(t, err) + + _genState := input.EVMKeeper.ExportGenesis(ctx) + require.Equal(t, genState, _genState) +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 4ffffad..85d3123 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" evmconfig "github.com/initia-labs/minievm/x/evm/config" "github.com/initia-labs/minievm/x/evm/types" @@ -19,6 +20,11 @@ type Keeper struct { cdc codec.Codec storeService corestoretypes.KVStoreService + accountKeeper types.AccountKeeper + communityPoolKeeper types.CommunityPoolKeeper + erc20Keeper types.IERC20Keeper + erc20StoresKeeper types.IERC20StoresKeeper + config evmconfig.EVMConfig // the address capable of executing a MsgUpdateParams message. Typically, this @@ -29,12 +35,22 @@ type Keeper struct { Params collections.Item[types.Params] VMRoot collections.Item[[]byte] VMStore collections.Map[[]byte, []byte] + + // erc20 stores of users + ERC20s collections.KeySet[[]byte] + ERC20Stores collections.KeySet[collections.Pair[[]byte, []byte]] + ERC20DenomsByContractAddr collections.Map[[]byte, string] + ERC20ContractAddrsByDenom collections.Map[string, []byte] + + precompiles precompiles } func NewKeeper( ac address.Codec, cdc codec.Codec, storeService corestoretypes.KVStoreService, + accountKeeper types.AccountKeeper, + communityPoolKeeper types.CommunityPoolKeeper, authority string, EVMConfig evmconfig.EVMConfig, ) *Keeper { @@ -52,18 +68,42 @@ func NewKeeper( ac: ac, cdc: cdc, storeService: storeService, - config: EVMConfig, + + accountKeeper: accountKeeper, + communityPoolKeeper: communityPoolKeeper, + + config: EVMConfig, Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), VMRoot: collections.NewItem(sb, types.VMRootKey, "vm_root", collections.BytesValue), VMStore: collections.NewMap(sb, types.VMStorePrefix, "vm_store", collections.BytesKey, 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)), + ERC20DenomsByContractAddr: collections.NewMap(sb, types.ERC20DenomsByContractAddrPrefix, "erc20_denoms_by_contract_addr", collections.BytesKey, collections.StringValue), + ERC20ContractAddrsByDenom: collections.NewMap(sb, types.ERC20ContractAddrsByDenomPrefix, "erc20_contract_addrs_by_denom", collections.StringKey, collections.BytesValue), + + precompiles: []precompile{}, } + // setup schema schema, err := sb.Build() if err != nil { panic(err) } + k.Schema = schema + k.erc20StoresKeeper = NewERC20StoresKeeper(k) + k.erc20Keeper, err = NewERC20Keeper(k) + if err != nil { + panic(err) + } + + // setup precompiles + if err := k.loadPrecompiles(); err != nil { + panic(err) + } + return k } @@ -77,3 +117,28 @@ func (k *Keeper) Logger(ctx context.Context) log.Logger { sdkCtx := sdk.UnwrapSDKContext(ctx) return sdkCtx.Logger().With("module", "x/"+types.ModuleName) } + +// ERC20Keeper returns the ERC20Keeper +func (k Keeper) ERC20Keeper() types.IERC20Keeper { + return k.erc20Keeper +} + +// ERC20StoresKeeper returns the ERC20StoresKeeper +func (k Keeper) ERC20StoresKeeper() types.IERC20StoresKeeper { + return k.erc20StoresKeeper +} + +// GetContractAddrByDenom returns contract address by denom +func (k Keeper) GetContractAddrByDenom(ctx context.Context, denom string) (common.Address, error) { + bz, err := k.ERC20ContractAddrsByDenom.Get(ctx, denom) + if err != nil { + return common.Address{}, err + } + + return common.BytesToAddress(bz), nil +} + +// GetDenomByContractAddr returns denom by contract address +func (k Keeper) GetDenomByContractAddr(ctx context.Context, contractAddr common.Address) (string, error) { + return k.ERC20DenomsByContractAddr.Get(ctx, contractAddr.Bytes()) +} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index f6b9f7d..e6535bd 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -2,10 +2,10 @@ package keeper import ( "context" + "encoding/hex" "github.com/ethereum/go-ethereum/common" - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -27,15 +27,17 @@ func (ms *msgServerImpl) Create(ctx context.Context, msg *types.MsgCreate) (*typ return nil, err } - codeBz := msg.Code - // argument validation if len(sender) != common.AddressLength { return nil, types.ErrInvalidAddressLength } - if len(codeBz) == 0 { + if len(msg.Code) == 0 { return nil, sdkerrors.ErrInvalidRequest.Wrap("empty code bytes") } + codeBz, err := hex.DecodeString(msg.Code) + if err != nil { + return nil, types.ErrInvalidHexString.Wrap(err.Error()) + } // check the sender is allowed publisher params, err := ms.Params.Get(ctx) @@ -60,21 +62,15 @@ func (ms *msgServerImpl) Create(ctx context.Context, msg *types.MsgCreate) (*typ } // deploy a contract - retBz, contractAddr, err := ms.EVMCreate(ctx, sender, codeBz) + caller := common.BytesToAddress(sender) + retBz, contractAddr, err := ms.EVMCreate(ctx, caller, codeBz) if err != nil { return nil, types.ErrEVMCallFailed.Wrap(err.Error()) } - // emit action events - sdkCtx := sdk.UnwrapSDKContext(ctx) - sdkCtx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeCall, - sdk.NewAttribute(types.AttributeKeyContract, contractAddr.Hex()), - sdk.NewAttribute(types.AttributeKeyRet, common.Bytes2Hex(retBz)), - )) - + retHex := common.Bytes2Hex(retBz) return &types.MsgCreateResponse{ - Result: retBz, + Result: retHex, ContractAddr: contractAddr.Hex(), }, nil } @@ -91,8 +87,6 @@ func (ms *msgServerImpl) Call(ctx context.Context, msg *types.MsgCall) (*types.M return nil, err } - inputBz := msg.Input - // argument validation if len(sender) != common.AddressLength { return nil, types.ErrInvalidAddressLength @@ -100,33 +94,19 @@ func (ms *msgServerImpl) Call(ctx context.Context, msg *types.MsgCall) (*types.M if len(contractAddr) != common.AddressLength { return nil, types.ErrInvalidAddressLength } - - retBz, logs, err := ms.EVMCall(ctx, sender, contractAddr, inputBz) + inputBz, err := hex.DecodeString(msg.Input) if err != nil { - return nil, types.ErrEVMCreateFailed.Wrap(err.Error()) + return nil, types.ErrInvalidHexString.Wrap(err.Error()) } - // emit action events - sdkCtx := sdk.UnwrapSDKContext(ctx) - sdkCtx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeCall, - sdk.NewAttribute(types.AttributeKeyContract, contractAddr.Hex()), - sdk.NewAttribute(types.AttributeKeyRet, common.Bytes2Hex(retBz)), - )) - - // emit logs events - for _, log := range logs { - dataInHex := common.Bytes2Hex(log.Data) - for _, topic := range log.Topics { - sdkCtx.EventManager().EmitEvent(sdk.NewEvent( - types.EventTypeLog, - sdk.NewAttribute(types.AttributeKeyTopic, topic), - sdk.NewAttribute(types.AttributeKeyRet, dataInHex), - )) - } + caller := common.BytesToAddress(sender) + retBz, logs, err := ms.EVMCall(ctx, caller, contractAddr, inputBz) + if err != nil { + return nil, types.ErrEVMCreateFailed.Wrap(err.Error()) } - return &types.MsgCallResponse{Result: retBz, Logs: logs}, nil + retHex := common.Bytes2Hex(retBz) + return &types.MsgCallResponse{Result: retHex, Logs: logs}, nil } // UpdateParams implements types.MsgServer. diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index 5f11159..c0a2dea 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -17,13 +17,12 @@ func Test_MsgServer_Create(t *testing.T) { ctx, input := createDefaultTestInput(t) _, _, addr := keyPubAddr() - counterBz, err := hex.DecodeString(strings.TrimPrefix(counter.CounterBin, "0x")) - require.NoError(t, err) + counterBin := strings.TrimPrefix(counter.CounterBin, "0x") msgServer := keeper.NewMsgServerImpl(&input.EVMKeeper) res, err := msgServer.Create(ctx, &types.MsgCreate{ Sender: addr.String(), - Code: counterBz, + Code: counterBin, }) require.NoError(t, err) require.NotEmpty(t, res.Result) @@ -38,7 +37,7 @@ func Test_MsgServer_Create(t *testing.T) { // allowed res, err = msgServer.Create(ctx, &types.MsgCreate{ Sender: addr.String(), - Code: counterBz, + Code: counterBin, }) require.NoError(t, err) require.NotEmpty(t, res.Result) @@ -48,7 +47,7 @@ func Test_MsgServer_Create(t *testing.T) { _, _, addr = keyPubAddr() _, err = msgServer.Create(ctx, &types.MsgCreate{ Sender: addr.String(), - Code: counterBz, + Code: counterBin, }) require.Error(t, err) } @@ -56,11 +55,12 @@ func Test_MsgServer_Create(t *testing.T) { func Test_MsgServer_Call(t *testing.T) { ctx, input := createDefaultTestInput(t) _, _, addr := keyPubAddr() + caller := common.BytesToAddress(addr.Bytes()) counterBz, err := hex.DecodeString(strings.TrimPrefix(counter.CounterBin, "0x")) require.NoError(t, err) - retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, addr, counterBz) + retBz, contractAddr, err := input.EVMKeeper.EVMCreate(ctx, caller, counterBz) require.NoError(t, err) require.NotEmpty(t, retBz) require.Len(t, contractAddr, 20) @@ -71,7 +71,7 @@ func Test_MsgServer_Call(t *testing.T) { queryInputBz, err := parsed.Pack("count") require.NoError(t, err) - queryRes, logs, err := input.EVMKeeper.EVMCall(ctx, addr, contractAddr, queryInputBz) + queryRes, logs, err := input.EVMKeeper.EVMCall(ctx, caller, contractAddr, queryInputBz) require.NoError(t, err) require.Equal(t, uint256.NewInt(0).Bytes32(), [32]byte(queryRes)) require.Empty(t, logs) @@ -83,13 +83,13 @@ func Test_MsgServer_Call(t *testing.T) { res, err := msgServer.Call(ctx, &types.MsgCall{ Sender: addr.String(), ContractAddr: contractAddr.Hex(), - Input: inputBz, + Input: common.Bytes2Hex(inputBz), }) require.NoError(t, err) require.Empty(t, res.Result) require.NotEmpty(t, res.Logs) - queryRes, logs, err = input.EVMKeeper.EVMCall(ctx, addr, contractAddr, queryInputBz) + queryRes, logs, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, queryInputBz) require.NoError(t, err) require.Equal(t, uint256.NewInt(1).Bytes32(), [32]byte(queryRes)) require.Empty(t, logs) diff --git a/x/evm/keeper/precompiles.go b/x/evm/keeper/precompiles.go new file mode 100644 index 0000000..b23b8e3 --- /dev/null +++ b/x/evm/keeper/precompiles.go @@ -0,0 +1,47 @@ +package keeper + +import ( + "context" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + erc20registry "github.com/initia-labs/minievm/x/evm/precompiles/erc20_registry" + "github.com/initia-labs/minievm/x/evm/types" +) + +// precompile is a precompiled contract. +type precompile struct { + addr common.Address + contract vm.PrecompiledContract +} + +// loadPrecompiles loads the precompiled contracts. +func (k *Keeper) loadPrecompiles() error { + erc20Registry, err := erc20registry.NewERC20Registry(k.erc20StoresKeeper) + if err != nil { + return err + } + + k.precompiles = precompiles{ + { + addr: common.BytesToAddress([]byte{0xf1}), + contract: erc20Registry, + }, + } + + return nil +} + +// precompiles is a list of precompiled contracts. +type precompiles []precompile + +// toMap converts the precompiles to a map. +func (ps precompiles) toMap(ctx context.Context) map[common.Address]vm.PrecompiledContract { + m := make(map[common.Address]vm.PrecompiledContract) + for _, p := range ps { + m[p.addr] = p.contract.(types.WithContext).WithContext(ctx) + } + + return m +} diff --git a/x/evm/keeper/query_server.go b/x/evm/keeper/query_server.go index 3f061dd..c8fb128 100644 --- a/x/evm/keeper/query_server.go +++ b/x/evm/keeper/query_server.go @@ -2,7 +2,10 @@ package keeper import ( "context" + "encoding/hex" + "fmt" + errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -20,7 +23,13 @@ func NewQueryServer(k *Keeper) types.QueryServer { } // Call implements types.QueryServer. -func (qs *queryServerImpl) Call(ctx context.Context, req *types.QueryCallRequest) (*types.QueryCallResponse, error) { +func (qs *queryServerImpl) Call(ctx context.Context, req *types.QueryCallRequest) (res *types.QueryCallResponse, err error) { + defer func() { + if r := recover(); r != nil { + err = errorsmod.Wrap(types.ErrEVMCallFailed, fmt.Sprintf("vm panic: %v", r)) + } + }() + sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx = sdkCtx.WithGasMeter(storetypes.NewGasMeter(qs.config.ContractQueryGasLimit)) @@ -34,13 +43,21 @@ func (qs *queryServerImpl) Call(ctx context.Context, req *types.QueryCallRequest return nil, err } - retBz, logs, err := qs.EVMCall(sdkCtx, sender, contractAddr, req.Input) + inputBz, err := hex.DecodeString(req.Input) + if err != nil { + return nil, err + } + + // use cache context to rollback writes + sdkCtx, _ = sdkCtx.CacheContext() + caller := common.BytesToAddress(sender) + retBz, logs, err := qs.EVMCall(sdkCtx, caller, contractAddr, inputBz) if err != nil { return nil, err } return &types.QueryCallResponse{ - Response: retBz, + Response: common.Bytes2Hex(retBz), UsedGas: sdkCtx.GasMeter().GasConsumedToLimit(), Logs: logs, }, nil @@ -92,6 +109,33 @@ func (qs *queryServerImpl) State(ctx context.Context, req *types.QueryStateReque }, 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) + if err != nil { + return nil, err + } + + return &types.QueryContractAddrByDenomResponse{ + Address: contractAddr.Hex(), + }, nil +} + +// Denom implements types.QueryServer. +func (qs *queryServerImpl) Denom(ctx context.Context, req *types.QueryDenomRequest) (*types.QueryDenomResponse, error) { + addr, err := types.ContractAddressFromString(qs.ac, req.ContractAddr) + if err != nil { + return nil, err + } + + denom, err := types.ContractAddrToDenom(ctx, qs, addr) + if err != nil { + return nil, err + } + + return &types.QueryDenomResponse{Denom: denom}, nil +} + // Params implements types.QueryServer. func (qs *queryServerImpl) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { params, err := qs.Keeper.Params.Get(ctx) diff --git a/x/evm/precompiles/erc20_registry/erc20_registry.go b/x/evm/precompiles/erc20_registry/erc20_registry.go new file mode 100644 index 0000000..95a69b1 --- /dev/null +++ b/x/evm/precompiles/erc20_registry/erc20_registry.go @@ -0,0 +1,113 @@ +package erc20registry + +import ( + "context" + "errors" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/initia-labs/minievm/x/evm/contracts/i_erc20_registry" + "github.com/initia-labs/minievm/x/evm/types" +) + +var _ vm.ExtendedPrecompiledContract = ERC20Registry{} +var _ vm.PrecompiledContract = ERC20Registry{} +var _ types.WithContext = ERC20Registry{} + +type ERC20Registry struct { + *abi.ABI + ctx context.Context + k types.IERC20StoresKeeper +} + +func NewERC20Registry(k types.IERC20StoresKeeper) (ERC20Registry, error) { + abi, err := i_erc20_registry.IErc20RegistryMetaData.GetAbi() + if err != nil { + return ERC20Registry{}, err + } + + return ERC20Registry{ABI: abi, k: k}, nil +} + +func (e ERC20Registry) WithContext(ctx context.Context) vm.PrecompiledContract { + e.ctx = ctx + return e +} + +const ( + METHOD_REGISTER = "register_erc20" + METHOD_REGISTER_STORE = "register_erc20_store" + METHOD_IS_STORE_REGISTERED = "is_erc20_store_registered" +) + +// ExtendedRun implements vm.ExtendedPrecompiledContract. +func (e ERC20Registry) ExtendedRun(caller vm.ContractRef, input []byte, suppliedGas uint64, readOnly bool) (resBz []byte, usedGas uint64, err error) { + method, err := e.ABI.MethodById(input) + if err != nil { + return nil, 0, err + } + + args, err := method.Inputs.Unpack(input[4:]) + if err != nil { + return nil, 0, err + } + + ctx := sdk.UnwrapSDKContext(e.ctx).WithGasMeter(storetypes.NewGasMeter(suppliedGas)) + switch method.Name { + case METHOD_REGISTER: + if readOnly { + return nil, 0, types.ErrNonReadOnlyMethod.Wrap(method.Name) + } + + if err := e.k.Register(ctx, caller.Address()); err != nil { + return nil, 0, err + } + case METHOD_REGISTER_STORE: + if readOnly { + return nil, 0, types.ErrNonReadOnlyMethod.Wrap(method.Name) + } + + var registerArgs RegisterArguments + if err := method.Inputs.Copy(®isterArgs, args); err != nil { + return nil, 0, err + } + + if err := e.k.RegisterStore(ctx, registerArgs.Account.Bytes(), caller.Address()); err != nil { + return nil, 0, err + } + case METHOD_IS_STORE_REGISTERED: + var isRegisteredArgs IsRegisteredArguments + if err := method.Inputs.Copy(&isRegisteredArgs, args); err != nil { + return nil, 0, err + } + + ok, err := e.k.IsStoreRegistered(ctx, isRegisteredArgs.Account.Bytes(), caller.Address()) + if err != nil { + return nil, 0, err + } + + resBz, err = method.Outputs.Pack(ok) + if err != nil { + return nil, 0, err + } + default: + return nil, 0, types.ErrUnknownPrecompileMethod.Wrap(method.Name) + } + + usedGas = ctx.GasMeter().GasConsumedToLimit() + return resBz, usedGas, nil +} + +// RequiredGas implements vm.PrecompiledContract. +func (e ERC20Registry) RequiredGas(input []byte) uint64 { + return 0 +} + +// Run implements vm.PrecompiledContract. +func (e ERC20Registry) Run(input []byte) ([]byte, error) { + return nil, errors.New("the ERC20Registry works exclusively with ExtendedRun") +} diff --git a/x/evm/precompiles/erc20_registry/erc20_registry_test.go b/x/evm/precompiles/erc20_registry/erc20_registry_test.go new file mode 100644 index 0000000..f112ceb --- /dev/null +++ b/x/evm/precompiles/erc20_registry/erc20_registry_test.go @@ -0,0 +1,158 @@ +package erc20registry_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/log" + "cosmossdk.io/store" + storemetrics "cosmossdk.io/store/metrics" + storetypes "cosmossdk.io/store/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + db "github.com/cosmos/cosmos-db" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + contracts "github.com/initia-labs/minievm/x/evm/contracts/i_erc20_registry" + precompiles "github.com/initia-labs/minievm/x/evm/precompiles/erc20_registry" + "github.com/initia-labs/minievm/x/evm/types" +) + +func setup() (sdk.Context, types.IERC20StoresKeeper) { + kv := db.NewMemDB() + cms := store.NewCommitMultiStore(kv, log.NewNopLogger(), storemetrics.NewNoOpMetrics()) + return sdk.NewContext(cms, cmtproto.Header{}, false, log.NewNopLogger()), ERC20StoresKeeper{ + erc20s: make(map[string]bool), + stores: make(map[string]map[string]bool), + } +} + +var _ types.IERC20StoresKeeper = ERC20StoresKeeper{} + +type ERC20StoresKeeper struct { + erc20s map[string]bool + stores map[string]map[string]bool +} + +const REGISTER_GAS storetypes.Gas = 300 +const REGISTER_STORE_GAS storetypes.Gas = 200 +const IS_STORE_REGISTERED_GAS storetypes.Gas = 100 + +func (e ERC20StoresKeeper) Register(ctx context.Context, contractAddr common.Address) error { + sdk.UnwrapSDKContext(ctx).GasMeter().ConsumeGas(REGISTER_GAS, "register gas") + + e.erc20s[contractAddr.Hex()] = true + return nil +} + +// IsRegistered implements types.IERC20StoresKeeper. +func (e ERC20StoresKeeper) IsStoreRegistered(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) (bool, error) { + sdk.UnwrapSDKContext(ctx).GasMeter().ConsumeGas(IS_STORE_REGISTERED_GAS, "is_register gas") + + store, ok := e.stores[addr.String()] + if !ok { + return false, nil + } + + _, ok = store[contractAddr.Hex()] + return ok, nil +} + +// Register implements types.IERC20StoresKeeper. +func (e ERC20StoresKeeper) RegisterStore(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) error { + sdk.UnwrapSDKContext(ctx).GasMeter().ConsumeGas(REGISTER_STORE_GAS, "register gas") + + _, ok := e.stores[addr.String()] + if !ok { + e.stores[addr.String()] = make(map[string]bool) + } + + e.stores[addr.String()][contractAddr.Hex()] = true + return nil +} + +func Test_ERC20Registry(t *testing.T) { + ctx, k := setup() + + registry, err := precompiles.NewERC20Registry(k) + require.NoError(t, err) + + // set context + registry = registry.WithContext(ctx).(precompiles.ERC20Registry) + + erc20Addr := common.HexToAddress("0x1") + accountAddr := common.HexToAddress("0x2") + abi, err := contracts.IErc20RegistryMetaData.GetAbi() + require.NoError(t, err) + + // register erc20 + bz, err := abi.Pack(precompiles.METHOD_REGISTER) + require.NoError(t, err) + + // out of gas panic + require.Panics(t, func() { + _, _, _ = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_GAS-1, false) + }) + + // non read only method fail + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_GAS, true) + require.Error(t, err) + + // success + _, usedGas, err := registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_GAS, false) + require.NoError(t, err) + require.Equal(t, usedGas, uint64(REGISTER_GAS)) + + // check erc20 registered + require.True(t, k.(ERC20StoresKeeper).erc20s[erc20Addr.Hex()]) + + // check unregistered + bz, err = abi.Pack(precompiles.METHOD_IS_STORE_REGISTERED, accountAddr) + require.NoError(t, err) + + resBz, usedGas, err := registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, IS_STORE_REGISTERED_GAS, true) + require.NoError(t, err) + require.Equal(t, usedGas, uint64(IS_STORE_REGISTERED_GAS)) + + res, err := abi.Methods[precompiles.METHOD_IS_STORE_REGISTERED].Outputs.Unpack(resBz) + require.NoError(t, err) + require.False(t, res[0].(bool)) + + // register store + bz, err = abi.Pack(precompiles.METHOD_REGISTER_STORE, accountAddr) + require.NoError(t, err) + + // out of gas panic + require.Panics(t, func() { + _, _, _ = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_STORE_GAS-1, false) + }) + + // non read only method fail + _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_STORE_GAS, true) + require.Error(t, err) + + // success + _, usedGas, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, REGISTER_STORE_GAS, false) + require.NoError(t, err) + require.Equal(t, usedGas, uint64(REGISTER_STORE_GAS)) + + // check registered + bz, err = abi.Pack(precompiles.METHOD_IS_STORE_REGISTERED, accountAddr) + require.NoError(t, err) + + // out of gas panic + require.Panics(t, func() { + _, _, _ = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, IS_STORE_REGISTERED_GAS-1, true) + }) + + resBz, usedGas, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, IS_STORE_REGISTERED_GAS, true) + require.NoError(t, err) + require.Equal(t, usedGas, uint64(IS_STORE_REGISTERED_GAS)) + + res, err = abi.Methods[precompiles.METHOD_IS_STORE_REGISTERED].Outputs.Unpack(resBz) + require.NoError(t, err) + require.True(t, res[0].(bool)) +} diff --git a/x/evm/precompiles/erc20_registry/types.go b/x/evm/precompiles/erc20_registry/types.go new file mode 100644 index 0000000..4456482 --- /dev/null +++ b/x/evm/precompiles/erc20_registry/types.go @@ -0,0 +1,11 @@ +package erc20registry + +import "github.com/ethereum/go-ethereum/common" + +type RegisterArguments struct { + Account common.Address `abi:"account"` +} + +type IsRegisteredArguments struct { + Account common.Address `abi:"account"` +} diff --git a/x/evm/types/address.go b/x/evm/types/address.go index d8ec9e6..06cccd2 100644 --- a/x/evm/types/address.go +++ b/x/evm/types/address.go @@ -2,10 +2,25 @@ package types import ( "cosmossdk.io/core/address" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) +// 0x0 null address +var NullAddress common.Address = common.HexToAddress("0x0") + +// 0x1 std address +var StdAddress common.Address = common.HexToAddress("0x1") + +// 0xf1 ERC20 precompile address +var ERC20PrecompileAddress common.Address = common.HexToAddress("0xf1") + +func FactoryAddress() common.Address { + return crypto.CreateAddress(StdAddress, 0) +} + // Parse string contract address to sdk.AccAddress func ContractAddressFromString(ac address.Codec, contractAddrInString string) (contractAddr common.Address, err error) { if common.IsHexAddress(contractAddrInString) { @@ -18,3 +33,11 @@ func ContractAddressFromString(ac address.Codec, contractAddrInString string) (c return contractAddr, nil } + +func CosmosAddressToEthAddress(addr sdk.AccAddress) (common.Address, error) { + if len(addr.Bytes()) != 20 { + return common.Address{}, ErrInvalidAddressLength + } + + return common.BytesToAddress(addr.Bytes()), nil +} diff --git a/x/evm/types/auth.go b/x/evm/types/auth.go new file mode 100644 index 0000000..f872b9a --- /dev/null +++ b/x/evm/types/auth.go @@ -0,0 +1,26 @@ +package types + +import ( + "fmt" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var ( + _ sdk.AccountI = (*ContractAccount)(nil) + _ authtypes.GenesisAccount = (*ContractAccount)(nil) +) + +// NewContractAccountWithAddress create new contract account with the given address. +func NewContractAccountWithAddress(addr sdk.AccAddress) *ContractAccount { + return &ContractAccount{ + authtypes.NewBaseAccountWithAddress(addr), + } +} + +// SetPubKey - Implements AccountI +func (ma ContractAccount) SetPubKey(pubKey cryptotypes.PubKey) error { + return fmt.Errorf("not supported for contract accounts") +} diff --git a/x/evm/types/auth.pb.go b/x/evm/types/auth.pb.go new file mode 100644 index 0000000..2637a92 --- /dev/null +++ b/x/evm/types/auth.pb.go @@ -0,0 +1,326 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: minievm/evm/v1/auth.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types "github.com/cosmos/cosmos-sdk/x/auth/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ContractAccount defines an account for contract account. +type ContractAccount struct { + *types.BaseAccount `protobuf:"bytes,1,opt,name=base_account,json=baseAccount,proto3,embedded=base_account" json:"base_account,omitempty"` +} + +func (m *ContractAccount) Reset() { *m = ContractAccount{} } +func (m *ContractAccount) String() string { return proto.CompactTextString(m) } +func (*ContractAccount) ProtoMessage() {} +func (*ContractAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_a01464d2d75c2977, []int{0} +} +func (m *ContractAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ContractAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ContractAccount.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 *ContractAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_ContractAccount.Merge(m, src) +} +func (m *ContractAccount) XXX_Size() int { + return m.Size() +} +func (m *ContractAccount) XXX_DiscardUnknown() { + xxx_messageInfo_ContractAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_ContractAccount proto.InternalMessageInfo + +func init() { + proto.RegisterType((*ContractAccount)(nil), "minievm.evm.v1.ContractAccount") +} + +func init() { proto.RegisterFile("minievm/evm/v1/auth.proto", fileDescriptor_a01464d2d75c2977) } + +var fileDescriptor_a01464d2d75c2977 = []byte{ + // 249 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xcd, 0xcc, 0xcb, + 0x4c, 0x2d, 0xcb, 0xd5, 0x07, 0xe1, 0x32, 0x43, 0xfd, 0xc4, 0xd2, 0x92, 0x0c, 0xbd, 0x82, 0xa2, + 0xfc, 0x92, 0x7c, 0x21, 0x3e, 0xa8, 0x94, 0x1e, 0x08, 0x97, 0x19, 0x4a, 0x09, 0x26, 0xe6, 0x66, + 0xe6, 0xe5, 0xeb, 0x83, 0x49, 0x88, 0x12, 0x29, 0x91, 0xf4, 0xfc, 0xf4, 0x7c, 0x30, 0x53, 0x1f, + 0xc4, 0x82, 0x8a, 0xca, 0x25, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0x83, 0xcd, 0xd2, 0x2f, 0x33, 0x4c, + 0x4a, 0x2d, 0x49, 0x44, 0x36, 0x58, 0xa9, 0x8a, 0x8b, 0xdf, 0x39, 0x3f, 0xaf, 0xa4, 0x28, 0x31, + 0xb9, 0xc4, 0x31, 0x39, 0x39, 0xbf, 0x34, 0xaf, 0x44, 0xc8, 0x93, 0x8b, 0x27, 0x29, 0xb1, 0x38, + 0x35, 0x3e, 0x11, 0xc2, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x36, 0x52, 0xd0, 0x83, 0x98, 0xa4, + 0x07, 0xd6, 0x0c, 0x35, 0x49, 0xcf, 0x29, 0xb1, 0x38, 0x15, 0xaa, 0xcf, 0x89, 0xe5, 0xc2, 0x3d, + 0x79, 0xc6, 0x20, 0xee, 0x24, 0x84, 0x90, 0x95, 0x4c, 0xc7, 0x02, 0x79, 0x86, 0xae, 0xe7, 0x1b, + 0xb4, 0x84, 0x41, 0x5e, 0x42, 0xb3, 0xc8, 0xc9, 0xe5, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, + 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, + 0xe5, 0x18, 0xa2, 0xb4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x33, + 0xf3, 0x32, 0x4b, 0x32, 0x13, 0x75, 0x73, 0x12, 0x93, 0x8a, 0xf5, 0x61, 0x01, 0x54, 0x01, 0x0e, + 0xa2, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0x47, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x28, 0x49, 0x6d, 0x72, 0x3e, 0x01, 0x00, 0x00, +} + +func (m *ContractAccount) 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 *ContractAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ContractAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BaseAccount != nil { + { + size, err := m.BaseAccount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuth(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAuth(dAtA []byte, offset int, v uint64) int { + offset -= sovAuth(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ContractAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BaseAccount != nil { + l = m.BaseAccount.Size() + n += 1 + l + sovAuth(uint64(l)) + } + return n +} + +func sovAuth(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuth(x uint64) (n int) { + return sovAuth(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ContractAccount) 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 ErrIntOverflowAuth + } + 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: ContractAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ContractAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAccount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuth + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuth + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuth + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BaseAccount == nil { + m.BaseAccount = &types.BaseAccount{} + } + if err := m.BaseAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuth(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuth + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuth(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuth + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuth + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuth + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAuth + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuth + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuth + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuth = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuth = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuth = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/evm/types/codec.go b/x/evm/types/codec.go index 8757d4c..e403c06 100644 --- a/x/evm/types/codec.go +++ b/x/evm/types/codec.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/legacy" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" // this line is used by starport scaffolding # 1 "github.com/cosmos/cosmos-sdk/types/msgservice" @@ -15,6 +16,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { legacy.RegisterAminoMsg(cdc, &MsgCreate{}, "evm/MsgCreate") legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "evm/MsgUpdateParams") + cdc.RegisterConcrete(&ContractAccount{}, "evm/ContractAccount", nil) + } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { @@ -25,5 +28,15 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgUpdateParams{}, ) + // auth account registration + registry.RegisterImplementations( + (*sdk.AccountI)(nil), + &ContractAccount{}, + ) + registry.RegisterImplementations( + (*authtypes.GenesisAccount)(nil), + &ContractAccount{}, + ) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/evm/types/denom.go b/x/evm/types/denom.go new file mode 100644 index 0000000..fe9865d --- /dev/null +++ b/x/evm/types/denom.go @@ -0,0 +1,45 @@ +package types + +import ( + "context" + "errors" + "strings" + + "cosmossdk.io/collections" + "github.com/ethereum/go-ethereum/common" +) + +const DENOM_PREFIX = "evm/" + +type ERC20Keeper interface { + GetContractAddrByDenom(context.Context, string) (common.Address, error) + GetDenomByContractAddr(context.Context, common.Address) (string, error) +} + +func DenomToContractAddr(ctx context.Context, k ERC20Keeper, denom string) (common.Address, error) { + if strings.HasPrefix(denom, DENOM_PREFIX) { + contractAddrInString := strings.TrimPrefix(denom, DENOM_PREFIX) + if !common.IsHexAddress(contractAddrInString) { + return common.Address{}, ErrInvalidDenom + } + + return common.HexToAddress(contractAddrInString), nil + } + + return k.GetContractAddrByDenom(ctx, denom) +} + +func ContractAddrToDenom(ctx context.Context, k ERC20Keeper, contractAddr common.Address) (string, error) { + denom, err := k.GetDenomByContractAddr(ctx, contractAddr) + if err != nil && errors.Is(err, collections.ErrNotFound) { + return DENOM_PREFIX + strings.TrimPrefix(contractAddr.Hex(), "0x"), nil + } else if err != nil { + return "", err + } + + return denom, nil +} + +func IsERC20Denom(denom string) bool { + return strings.HasPrefix(denom, DENOM_PREFIX) +} diff --git a/x/evm/types/errors.go b/x/evm/types/errors.go index bf9d7e9..7fd7e40 100644 --- a/x/evm/types/errors.go +++ b/x/evm/types/errors.go @@ -7,7 +7,16 @@ import ( // EVM Errors var ( // ErrInvalidAddressLength error for the invalid address length - ErrInvalidAddressLength = errorsmod.Register(ModuleName, 2, "address must be 20 bytes to use EVM") - ErrEVMCallFailed = errorsmod.Register(ModuleName, 3, "EVMCall failed") - ErrEVMCreateFailed = errorsmod.Register(ModuleName, 4, "EVMCreate failed") + ErrInvalidAddressLength = errorsmod.Register(ModuleName, 2, "Invalid address length: address must be 20 bytes to use EVM") + ErrEVMCallFailed = errorsmod.Register(ModuleName, 3, "EVMCall failed") + ErrEVMCreateFailed = errorsmod.Register(ModuleName, 4, "EVMCreate failed") + ErrUnknownPrecompileMethod = errorsmod.Register(ModuleName, 5, "Unknown precompile method") + ErrInvalidHexString = errorsmod.Register(ModuleName, 6, "Invalid hex string") + ErrFailedToDecodeOutput = errorsmod.Register(ModuleName, 7, "Failed to decode output") + ErrInvalidDenom = errorsmod.Register(ModuleName, 8, "Invalid denom") + ErrInvalidRequest = errorsmod.Register(ModuleName, 9, "Invalid request") + ErrFailedToPackABI = errorsmod.Register(ModuleName, 10, "Failed to pack ABI") + ErrFailedToUnpackABI = errorsmod.Register(ModuleName, 11, "Failed to unpack ABI") + ErrNonReadOnlyMethod = errorsmod.Register(ModuleName, 12, "Failed to call precompile in readonly mode") + ErrAddressAlreadyExists = errorsmod.Register(ModuleName, 13, "Address already exists") ) diff --git a/x/evm/types/events.go b/x/evm/types/events.go index a063675..a461495 100644 --- a/x/evm/types/events.go +++ b/x/evm/types/events.go @@ -5,8 +5,12 @@ const ( EventTypeCreate = "create" EventTypeLog = "log" + // erc20 events + EventTypeERC20Created = "erc20_created" + AttributeKeyContract = "contract" AttributeKeyTopic = "topic" AttributeKeyData = "data" AttributeKeyRet = "ret" + AttributeKeyDenom = "denom" ) diff --git a/x/evm/types/expected_keeper.go b/x/evm/types/expected_keeper.go index ab1254f..ffd772a 100644 --- a/x/evm/types/expected_keeper.go +++ b/x/evm/types/expected_keeper.go @@ -1 +1,60 @@ package types + +import ( + "context" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +// AccountKeeper is expected keeper for auth module +type AccountKeeper interface { + NewAccount(ctx context.Context, acc sdk.AccountI) sdk.AccountI + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + SetAccount(ctx context.Context, acc sdk.AccountI) + HasAccount(ctx context.Context, addr sdk.AccAddress) bool + + NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + NextAccountNumber(ctx context.Context) uint64 +} + +type CommunityPoolKeeper interface { + // FundCommunityPool allows an account to directly fund the community fund pool. + FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error +} + +type IERC20StoresKeeper interface { + Register(ctx context.Context, contractAddr common.Address) error + RegisterStore(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) error + IsStoreRegistered(ctx context.Context, addr sdk.AccAddress, contractAddr common.Address) (bool, error) +} + +type IERC20Keeper interface { + // balance + GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) (math.Int, error) + GetPaginatedBalances(ctx context.Context, pageReq *query.PageRequest, addr sdk.AccAddress) (sdk.Coins, *query.PageResponse, error) + GetPaginatedSupply(ctx context.Context, pageReq *query.PageRequest) (sdk.Coins, *query.PageResponse, error) + IterateAccountBalances(ctx context.Context, addr sdk.AccAddress, cb func(sdk.Coin) (bool, error)) error + IterateSupply(ctx context.Context, cb func(supply sdk.Coin) (bool, error)) error + + // operations + SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + MintCoins(ctx context.Context, addr sdk.AccAddress, amount sdk.Coins) error + BurnCoins(ctx context.Context, addr sdk.AccAddress, amount sdk.Coins) error + + // supply + GetSupply(ctx context.Context, denom string) (math.Int, error) + HasSupply(ctx context.Context, denom string) (bool, error) + + // fungible asset + GetMetadata(ctx context.Context, denom string) (banktypes.Metadata, error) +} + +type WithContext interface { + WithContext(ctx context.Context) vm.PrecompiledContract +} diff --git a/x/evm/types/genesis.go b/x/evm/types/genesis.go index 08a2563..4f83640 100644 --- a/x/evm/types/genesis.go +++ b/x/evm/types/genesis.go @@ -1,6 +1,7 @@ package types import ( + bytes "bytes" "errors" "cosmossdk.io/core/address" @@ -24,3 +25,7 @@ func (genState *GenesisState) Validate(ac address.Codec) error { return genState.Params.Validate(ac) } + +func (genState GenesisState) IsExported() bool { + return !bytes.Equal(genState.StateRoot, coretypes.EmptyRootHash[:]) +} diff --git a/x/evm/types/genesis.pb.go b/x/evm/types/genesis.pb.go index 86f09c9..9a74fb0 100644 --- a/x/evm/types/genesis.pb.go +++ b/x/evm/types/genesis.pb.go @@ -31,6 +31,9 @@ type GenesisState struct { StateRoot []byte `protobuf:"bytes,2,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty"` // vm kv store KeyValues []GenesisKeyValue `protobuf:"bytes,3,rep,name=key_values,json=keyValues,proto3" json:"key_values" yaml:"key_values"` + // erc20 stores + Erc20Stores []GenesisERC20Stores `protobuf:"bytes,4,rep,name=erc20_stores,json=erc20Stores,proto3" json:"erc20_stores" yaml:"erc20_stores"` + DenomAddresses []GenesisDenomAddress `protobuf:"bytes,5,rep,name=denom_addresses,json=denomAddresses,proto3" json:"denom_addresses" yaml:"denom_addresses"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -87,9 +90,21 @@ func (m *GenesisState) GetKeyValues() []GenesisKeyValue { return nil } -// GenesisDenom defines a evm denom that is defined within genesis -// state. The structure contains DenomAuthorityMetadata which defines the -// denom's admin. +func (m *GenesisState) GetErc20Stores() []GenesisERC20Stores { + if m != nil { + return m.Erc20Stores + } + return nil +} + +func (m *GenesisState) GetDenomAddresses() []GenesisDenomAddress { + if m != nil { + return m.DenomAddresses + } + return nil +} + +// GenesisKeyValue defines store KV values. type GenesisKeyValue struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` @@ -142,35 +157,152 @@ func (m *GenesisKeyValue) GetValue() []byte { return nil } +// GenesisERC20Stores defines erc20 contract addresses of an account. +type GenesisERC20Stores struct { + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Stores [][]byte `protobuf:"bytes,2,rep,name=stores,proto3" json:"stores,omitempty"` +} + +func (m *GenesisERC20Stores) Reset() { *m = GenesisERC20Stores{} } +func (m *GenesisERC20Stores) String() string { return proto.CompactTextString(m) } +func (*GenesisERC20Stores) ProtoMessage() {} +func (*GenesisERC20Stores) Descriptor() ([]byte, []int) { + return fileDescriptor_2f1b77281e8b59af, []int{2} +} +func (m *GenesisERC20Stores) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisERC20Stores) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisERC20Stores.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 *GenesisERC20Stores) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisERC20Stores.Merge(m, src) +} +func (m *GenesisERC20Stores) XXX_Size() int { + return m.Size() +} +func (m *GenesisERC20Stores) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisERC20Stores.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisERC20Stores proto.InternalMessageInfo + +func (m *GenesisERC20Stores) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +func (m *GenesisERC20Stores) GetStores() [][]byte { + if m != nil { + return m.Stores + } + return nil +} + +// GenesisDenomAddress defines erc20 contract address of denom. +type GenesisDenomAddress struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + ContractAddress []byte `protobuf:"bytes,2,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` +} + +func (m *GenesisDenomAddress) Reset() { *m = GenesisDenomAddress{} } +func (m *GenesisDenomAddress) String() string { return proto.CompactTextString(m) } +func (*GenesisDenomAddress) ProtoMessage() {} +func (*GenesisDenomAddress) Descriptor() ([]byte, []int) { + return fileDescriptor_2f1b77281e8b59af, []int{3} +} +func (m *GenesisDenomAddress) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisDenomAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisDenomAddress.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 *GenesisDenomAddress) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisDenomAddress.Merge(m, src) +} +func (m *GenesisDenomAddress) XXX_Size() int { + return m.Size() +} +func (m *GenesisDenomAddress) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisDenomAddress.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisDenomAddress proto.InternalMessageInfo + +func (m *GenesisDenomAddress) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *GenesisDenomAddress) GetContractAddress() []byte { + if m != nil { + return m.ContractAddress + } + return nil +} + func init() { proto.RegisterType((*GenesisState)(nil), "minievm.evm.v1.GenesisState") proto.RegisterType((*GenesisKeyValue)(nil), "minievm.evm.v1.GenesisKeyValue") + proto.RegisterType((*GenesisERC20Stores)(nil), "minievm.evm.v1.GenesisERC20Stores") + proto.RegisterType((*GenesisDenomAddress)(nil), "minievm.evm.v1.GenesisDenomAddress") } func init() { proto.RegisterFile("minievm/evm/v1/genesis.proto", fileDescriptor_2f1b77281e8b59af) } var fileDescriptor_2f1b77281e8b59af = []byte{ - // 308 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xc9, 0xcd, 0xcc, 0xcb, - 0x4c, 0x2d, 0xcb, 0xd5, 0x07, 0xe1, 0x32, 0x43, 0xfd, 0xf4, 0xd4, 0xbc, 0xd4, 0xe2, 0xcc, 0x62, - 0xbd, 0x82, 0xa2, 0xfc, 0x92, 0x7c, 0x21, 0x3e, 0xa8, 0xac, 0x1e, 0x08, 0x97, 0x19, 0x4a, 0x89, - 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0xa5, 0xf4, 0x41, 0x2c, 0x88, 0x2a, 0x29, 0x29, 0x34, 0x33, 0x4a, - 0x2a, 0x0b, 0x52, 0xa1, 0x26, 0x28, 0xed, 0x63, 0xe4, 0xe2, 0x71, 0x87, 0x98, 0x19, 0x5c, 0x92, - 0x58, 0x92, 0x2a, 0x64, 0xc2, 0xc5, 0x56, 0x90, 0x58, 0x94, 0x98, 0x5b, 0x2c, 0xc1, 0xa8, 0xc0, - 0xa8, 0xc1, 0x6d, 0x24, 0xa6, 0x87, 0x6a, 0x87, 0x5e, 0x00, 0x58, 0xd6, 0x89, 0xe5, 0xc4, 0x3d, - 0x79, 0x86, 0x20, 0xa8, 0x5a, 0x21, 0x59, 0x2e, 0xae, 0x62, 0x90, 0xf6, 0xf8, 0xa2, 0xfc, 0xfc, - 0x12, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x4e, 0xb0, 0x48, 0x50, 0x7e, 0x7e, 0x89, 0x50, - 0x24, 0x17, 0x57, 0x76, 0x6a, 0x65, 0x7c, 0x59, 0x62, 0x4e, 0x69, 0x6a, 0xb1, 0x04, 0xb3, 0x02, - 0xb3, 0x06, 0xb7, 0x91, 0x3c, 0xba, 0xc1, 0x50, 0x67, 0x78, 0xa7, 0x56, 0x86, 0x81, 0xd4, 0x39, - 0x49, 0x82, 0x6c, 0xf8, 0x74, 0x4f, 0x5e, 0xb0, 0x32, 0x31, 0x37, 0xc7, 0x4a, 0x09, 0x61, 0x80, - 0x52, 0x10, 0x67, 0x36, 0x54, 0x51, 0xb1, 0x92, 0x25, 0x17, 0x3f, 0x9a, 0x46, 0x21, 0x01, 0x2e, - 0xe6, 0xec, 0xd4, 0x4a, 0xb0, 0xfb, 0x79, 0x82, 0x40, 0x4c, 0x21, 0x11, 0x2e, 0x56, 0xb0, 0x56, - 0xa8, 0xcb, 0x20, 0x1c, 0x27, 0x97, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, - 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, - 0xd2, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xcc, 0xcb, 0x2c, - 0xc9, 0x4c, 0xd4, 0xcd, 0x49, 0x4c, 0x2a, 0xd6, 0x87, 0x05, 0x64, 0x05, 0x38, 0x28, 0xc1, 0xe1, - 0x98, 0xc4, 0x06, 0x0e, 0x48, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x73, 0x48, 0xe7, 0x5b, - 0xaa, 0x01, 0x00, 0x00, + // 457 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0xe3, 0xba, 0x0d, 0xca, 0xc4, 0x6a, 0xca, 0xb6, 0x8a, 0x4c, 0x00, 0x27, 0x5a, 0x2e, + 0x01, 0x09, 0xbb, 0x0d, 0x5c, 0xe0, 0x46, 0x28, 0x70, 0xe0, 0x82, 0xb6, 0x52, 0x25, 0xb8, 0x44, + 0x9b, 0x64, 0x65, 0xac, 0xd8, 0xde, 0xc8, 0xbb, 0xb5, 0xf0, 0x5b, 0xf4, 0xb1, 0x7a, 0xec, 0x91, + 0x53, 0x85, 0x92, 0x37, 0xe0, 0x09, 0xd0, 0xfe, 0xb1, 0x28, 0xa6, 0x3d, 0xac, 0xb4, 0xb3, 0xf3, + 0xf9, 0xf7, 0xcd, 0x8c, 0x07, 0x9e, 0x64, 0x49, 0x9e, 0xb0, 0x32, 0x8b, 0xd4, 0x29, 0x4f, 0xa2, + 0x98, 0xe5, 0x4c, 0x24, 0x22, 0x5c, 0x17, 0x5c, 0x72, 0xb4, 0x6f, 0xb3, 0xa1, 0x3a, 0xe5, 0xc9, + 0xe0, 0x28, 0xe6, 0x31, 0xd7, 0xa9, 0x48, 0xdd, 0x8c, 0x6a, 0x30, 0x68, 0x30, 0x64, 0xb5, 0x66, + 0x96, 0x80, 0x2f, 0x5d, 0xf0, 0x3e, 0x19, 0xe6, 0x99, 0xa4, 0x92, 0xa1, 0xd7, 0xd0, 0x5e, 0xd3, + 0x82, 0x66, 0xc2, 0x77, 0x46, 0xce, 0xb8, 0x3b, 0xe9, 0x87, 0xff, 0x7a, 0x84, 0x5f, 0x74, 0x76, + 0xba, 0x7b, 0x75, 0x33, 0x6c, 0x11, 0xab, 0x45, 0x4f, 0x01, 0x84, 0xfa, 0x7c, 0x56, 0x70, 0x2e, + 0xfd, 0x9d, 0x91, 0x33, 0xf6, 0x48, 0x47, 0xbf, 0x10, 0xce, 0x25, 0xfa, 0x0a, 0xb0, 0x62, 0xd5, + 0xac, 0xa4, 0xe9, 0x05, 0x13, 0xbe, 0x3b, 0x72, 0xc7, 0xdd, 0xc9, 0xb0, 0x09, 0xb6, 0x65, 0x7c, + 0x66, 0xd5, 0xb9, 0xd2, 0x4d, 0x1f, 0x29, 0x87, 0xdf, 0x37, 0xc3, 0x87, 0x15, 0xcd, 0xd2, 0xb7, + 0xf8, 0x2f, 0x00, 0x93, 0xce, 0xca, 0x8a, 0x04, 0x9a, 0x83, 0xc7, 0x8a, 0xc5, 0xe4, 0x78, 0x26, + 0x24, 0x2f, 0x98, 0xf0, 0x77, 0x35, 0x1c, 0xdf, 0x03, 0xff, 0x40, 0xde, 0x4f, 0x8e, 0xcf, 0xb4, + 0x72, 0xfa, 0xd8, 0xf2, 0x0f, 0x0d, 0xff, 0x36, 0x05, 0x93, 0xae, 0x0e, 0x8d, 0x12, 0xa5, 0xd0, + 0x5b, 0xb2, 0x9c, 0x67, 0x33, 0xba, 0x5c, 0x16, 0x4c, 0x08, 0x26, 0xfc, 0x3d, 0x6d, 0xf3, 0xec, + 0x1e, 0x9b, 0x53, 0xa5, 0x7e, 0x67, 0xc4, 0xd3, 0xc0, 0xfa, 0xf4, 0x8d, 0x4f, 0x83, 0x84, 0xc9, + 0xfe, 0xf2, 0x96, 0x9a, 0x09, 0xfc, 0x06, 0x7a, 0x8d, 0x51, 0xa0, 0x03, 0x70, 0x57, 0xac, 0xd2, + 0x7f, 0xc4, 0x23, 0xea, 0x8a, 0x8e, 0x60, 0x4f, 0x0f, 0xc3, 0xce, 0xda, 0x04, 0xf8, 0x23, 0xa0, + 0xff, 0x1b, 0x45, 0x3e, 0x3c, 0xb0, 0x76, 0x96, 0x50, 0x87, 0xa8, 0x0f, 0x6d, 0x3b, 0xb6, 0x9d, + 0x91, 0x3b, 0xf6, 0x88, 0x8d, 0xf0, 0x39, 0x1c, 0xde, 0xd1, 0x89, 0x32, 0xd5, 0xb5, 0x6a, 0x4c, + 0x87, 0x98, 0x00, 0x3d, 0x87, 0x83, 0x05, 0xcf, 0x65, 0x41, 0x17, 0xb2, 0x6e, 0xcb, 0x56, 0xd5, + 0xab, 0xdf, 0xeb, 0x51, 0x9c, 0x5e, 0x6d, 0x02, 0xe7, 0x7a, 0x13, 0x38, 0xbf, 0x36, 0x81, 0x73, + 0xb9, 0x0d, 0x5a, 0xd7, 0xdb, 0xa0, 0xf5, 0x73, 0x1b, 0xb4, 0xbe, 0xbd, 0x88, 0x13, 0xf9, 0xfd, + 0x62, 0x1e, 0x2e, 0x78, 0x16, 0x25, 0x79, 0x22, 0x13, 0xfa, 0x32, 0xa5, 0x73, 0x11, 0xd5, 0xab, + 0xfb, 0x43, 0x2f, 0xaf, 0xde, 0xdc, 0x79, 0x5b, 0xaf, 0xee, 0xab, 0x3f, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x4c, 0xdd, 0xef, 0x53, 0x1c, 0x03, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -193,6 +325,34 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.DenomAddresses) > 0 { + for iNdEx := len(m.DenomAddresses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DenomAddresses[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if len(m.Erc20Stores) > 0 { + for iNdEx := len(m.Erc20Stores) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Erc20Stores[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } if len(m.KeyValues) > 0 { for iNdEx := len(m.KeyValues) - 1; iNdEx >= 0; iNdEx-- { { @@ -264,6 +424,82 @@ func (m *GenesisKeyValue) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GenesisERC20Stores) 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 *GenesisERC20Stores) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisERC20Stores) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Stores) > 0 { + for iNdEx := len(m.Stores) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Stores[iNdEx]) + copy(dAtA[i:], m.Stores[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Stores[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GenesisDenomAddress) 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 *GenesisDenomAddress) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisDenomAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ContractAddress) > 0 { + i -= len(m.ContractAddress) + copy(dAtA[i:], m.ContractAddress) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -293,6 +529,18 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.Erc20Stores) > 0 { + for _, e := range m.Erc20Stores { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.DenomAddresses) > 0 { + for _, e := range m.DenomAddresses { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -313,6 +561,42 @@ func (m *GenesisKeyValue) Size() (n int) { return n } +func (m *GenesisERC20Stores) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Stores) > 0 { + for _, b := range m.Stores { + l = len(b) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GenesisDenomAddress) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.ContractAddress) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + return n +} + func sovGenesis(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -449,6 +733,74 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20Stores", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20Stores = append(m.Erc20Stores, GenesisERC20Stores{}) + if err := m.Erc20Stores[len(m.Erc20Stores)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomAddresses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DenomAddresses = append(m.DenomAddresses, GenesisDenomAddress{}) + if err := m.DenomAddresses[len(m.DenomAddresses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) @@ -588,6 +940,238 @@ func (m *GenesisKeyValue) Unmarshal(dAtA []byte) error { } return nil } +func (m *GenesisERC20Stores) 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 ErrIntOverflowGenesis + } + 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: GenesisERC20Stores: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisERC20Stores: 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 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.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stores", 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.Stores = append(m.Stores, make([]byte, postIndex-iNdEx)) + copy(m.Stores[len(m.Stores)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisDenomAddress) 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 ErrIntOverflowGenesis + } + 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: GenesisDenomAddress: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisDenomAddress: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", 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.ContractAddress = append(m.ContractAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ContractAddress == nil { + m.ContractAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipGenesis(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index 20e49db..b9e6fc5 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -20,8 +20,12 @@ const ( // Keys for move store // Items are stored with the following key: values var ( - VMStorePrefix = []byte{0x21} // prefix for vm + VMStorePrefix = []byte{0x21} // prefix for vm + ERC20sPrefix = []byte{0x31} // prefix for erc20 stores + ERC20StoresPrefix = []byte{0x32} // prefix for erc20 stores + ERC20DenomsByContractAddrPrefix = []byte{0x33} // prefix for erc20 denoms + ERC20ContractAddrsByDenomPrefix = []byte{0x34} // prefix for erc20 denoms - ParamsKey = []byte{0x31} // key of parameters for module x/evm - VMRootKey = []byte{0x41} // key of evm state root + ParamsKey = []byte{0x41} // key of parameters for module x/evm + VMRootKey = []byte{0x51} // key of evm state root ) diff --git a/x/evm/types/log.go b/x/evm/types/log.go index afa7ac0..54a59ab 100644 --- a/x/evm/types/log.go +++ b/x/evm/types/log.go @@ -1,6 +1,7 @@ package types import ( + "github.com/ethereum/go-ethereum/common" coretypes "github.com/ethereum/go-ethereum/core/types" ) @@ -24,6 +25,6 @@ func NewLog(ethLog *coretypes.Log) Log { return Log{ Address: ethLog.Address.String(), Topics: topics, - Data: ethLog.Data, + Data: common.Bytes2Hex(ethLog.Data), } } diff --git a/x/evm/types/query.pb.go b/x/evm/types/query.pb.go index 1b73698..0773d5b 100644 --- a/x/evm/types/query.pb.go +++ b/x/evm/types/query.pb.go @@ -34,7 +34,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // QueryCodeRequest is the request type for the Query/Code RPC // method type QueryCodeRequest struct { - // contract address to query + // hex encoded contract address to query ContractAddr string `protobuf:"bytes,1,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` } @@ -113,7 +113,7 @@ var xxx_messageInfo_QueryCodeResponse proto.InternalMessageInfo // QueryStateRequest is the request type for the Query/State RPC // method type QueryStateRequest struct { - // contract address to query + // It can be cosmos address or hex encoded address (0x prefixed). ContractAddr string `protobuf:"bytes,1,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` // hex encoded hash string Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` @@ -197,10 +197,10 @@ var xxx_messageInfo_QueryStateResponse proto.InternalMessageInfo type QueryCallRequest struct { // sender address Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` - // contract address to call + // It can be cosmos address or hex encoded address (0x prefixed). ContractAddr string `protobuf:"bytes,2,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` - // call input bytes - Input []byte `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` + // hex encoded call input + Input string `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` } func (m *QueryCallRequest) Reset() { *m = QueryCallRequest{} } @@ -239,7 +239,8 @@ var xxx_messageInfo_QueryCallRequest proto.InternalMessageInfo // QueryCallResponse is the response type for the Query/Call RPC // method type QueryCallResponse struct { - Response []byte `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` + // hex encoded response bytes. + Response string `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` UsedGas uint64 `protobuf:"varint,2,opt,name=used_gas,json=usedGas,proto3" json:"used_gas,omitempty"` Logs []Log `protobuf:"bytes,3,rep,name=logs,proto3" json:"logs"` } @@ -277,6 +278,164 @@ func (m *QueryCallResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryCallResponse proto.InternalMessageInfo +// QueryContractAddrByDenomRequest is the request type for the Query/ContractAddrByDenom RPC +// method +type QueryContractAddrByDenomRequest struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryContractAddrByDenomRequest) Reset() { *m = QueryContractAddrByDenomRequest{} } +func (m *QueryContractAddrByDenomRequest) String() string { return proto.CompactTextString(m) } +func (*QueryContractAddrByDenomRequest) ProtoMessage() {} +func (*QueryContractAddrByDenomRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2bf9e0bee7cfd1a4, []int{6} +} +func (m *QueryContractAddrByDenomRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryContractAddrByDenomRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryContractAddrByDenomRequest.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 *QueryContractAddrByDenomRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryContractAddrByDenomRequest.Merge(m, src) +} +func (m *QueryContractAddrByDenomRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryContractAddrByDenomRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryContractAddrByDenomRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryContractAddrByDenomRequest proto.InternalMessageInfo + +// QueryContractAddrByDenomResponse is the response type for the Query/ContractAddrByDenom RPC +// method +type QueryContractAddrByDenomResponse struct { + // 0x prefixed hex address + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *QueryContractAddrByDenomResponse) Reset() { *m = QueryContractAddrByDenomResponse{} } +func (m *QueryContractAddrByDenomResponse) String() string { return proto.CompactTextString(m) } +func (*QueryContractAddrByDenomResponse) ProtoMessage() {} +func (*QueryContractAddrByDenomResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2bf9e0bee7cfd1a4, []int{7} +} +func (m *QueryContractAddrByDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryContractAddrByDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryContractAddrByDenomResponse.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 *QueryContractAddrByDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryContractAddrByDenomResponse.Merge(m, src) +} +func (m *QueryContractAddrByDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryContractAddrByDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryContractAddrByDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryContractAddrByDenomResponse proto.InternalMessageInfo + +// QueryDenomRequest is the request type for the Query/Denom RPC +// method +type QueryDenomRequest struct { + // It can be cosmos address or hex encoded address (0x prefixed). + ContractAddr string `protobuf:"bytes,1,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` +} + +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} +} +func (m *QueryDenomRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomRequest.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 *QueryDenomRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomRequest.Merge(m, src) +} +func (m *QueryDenomRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomRequest proto.InternalMessageInfo + +// QueryDenomResponse is the response type for the Query/Denom RPC +// method +type QueryDenomResponse struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +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} +} +func (m *QueryDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomResponse.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 *QueryDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomResponse.Merge(m, src) +} +func (m *QueryDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomResponse proto.InternalMessageInfo + // QueryParamsRequest is the request type for the Query/Params RPC method. type QueryParamsRequest struct { } @@ -285,7 +444,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{6} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{10} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -324,7 +483,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{7} + return fileDescriptor_2bf9e0bee7cfd1a4, []int{11} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -360,6 +519,10 @@ func init() { proto.RegisterType((*QueryStateResponse)(nil), "minievm.evm.v1.QueryStateResponse") proto.RegisterType((*QueryCallRequest)(nil), "minievm.evm.v1.QueryCallRequest") proto.RegisterType((*QueryCallResponse)(nil), "minievm.evm.v1.QueryCallResponse") + proto.RegisterType((*QueryContractAddrByDenomRequest)(nil), "minievm.evm.v1.QueryContractAddrByDenomRequest") + proto.RegisterType((*QueryContractAddrByDenomResponse)(nil), "minievm.evm.v1.QueryContractAddrByDenomResponse") + proto.RegisterType((*QueryDenomRequest)(nil), "minievm.evm.v1.QueryDenomRequest") + proto.RegisterType((*QueryDenomResponse)(nil), "minievm.evm.v1.QueryDenomResponse") proto.RegisterType((*QueryParamsRequest)(nil), "minievm.evm.v1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "minievm.evm.v1.QueryParamsResponse") } @@ -367,45 +530,53 @@ func init() { func init() { proto.RegisterFile("minievm/evm/v1/query.proto", fileDescriptor_2bf9e0bee7cfd1a4) } var fileDescriptor_2bf9e0bee7cfd1a4 = []byte{ - // 604 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0x93, 0x35, 0x2d, 0x9b, 0x37, 0xd0, 0xe6, 0x55, 0x53, 0x17, 0xa1, 0xac, 0x78, 0x42, - 0x4c, 0x15, 0x4d, 0x58, 0x99, 0x84, 0xb4, 0x1b, 0xe5, 0x80, 0x04, 0x3b, 0x40, 0xb8, 0x71, 0x99, - 0xdc, 0xc6, 0x0a, 0xd1, 0xd2, 0x38, 0x8d, 0x9d, 0x8a, 0x32, 0x8d, 0x03, 0xe2, 0x03, 0x20, 0xf1, - 0x05, 0x38, 0xee, 0xc8, 0xc7, 0xe8, 0x71, 0x12, 0x17, 0x4e, 0x08, 0x5a, 0x24, 0x90, 0xf8, 0x12, - 0xc8, 0x8e, 0x3b, 0xda, 0xb4, 0xab, 0xc4, 0x21, 0xd1, 0x7b, 0xf6, 0xdf, 0xef, 0xf7, 0xfc, 0xde, - 0x93, 0x81, 0xd9, 0x09, 0xa2, 0x80, 0xf4, 0x3a, 0x8e, 0xf8, 0x7a, 0xfb, 0x4e, 0x37, 0x25, 0x49, - 0xdf, 0x8e, 0x13, 0xca, 0x29, 0xbc, 0xa1, 0xf6, 0x6c, 0xf1, 0xf5, 0xf6, 0xcd, 0x0d, 0xdc, 0x09, - 0x22, 0xea, 0xc8, 0x7f, 0x26, 0x31, 0xcb, 0x3e, 0xf5, 0xa9, 0x34, 0x1d, 0x61, 0xa9, 0xd5, 0x9b, - 0x3e, 0xa5, 0x7e, 0x48, 0x1c, 0x1c, 0x07, 0x0e, 0x8e, 0x22, 0xca, 0x31, 0x0f, 0x68, 0xc4, 0xd4, - 0x6e, 0x1e, 0xc9, 0xfb, 0x31, 0x51, 0x7b, 0xe8, 0x01, 0x58, 0x7f, 0x2e, 0x32, 0x78, 0x44, 0x3d, - 0xe2, 0x92, 0x6e, 0x4a, 0x18, 0x87, 0xbb, 0xe0, 0x7a, 0x9b, 0x46, 0x3c, 0xc1, 0x6d, 0x7e, 0x8c, - 0x3d, 0x2f, 0xa9, 0xe8, 0x55, 0x7d, 0x6f, 0xc5, 0x5d, 0x1b, 0x2f, 0x3e, 0xf4, 0xbc, 0x04, 0xd5, - 0xc1, 0xc6, 0xc4, 0x41, 0x16, 0xd3, 0x88, 0x11, 0x08, 0x81, 0xd1, 0xa6, 0x1e, 0x91, 0x07, 0xd6, - 0x5c, 0x69, 0x1f, 0x1a, 0xbf, 0x3f, 0xed, 0xe8, 0xe8, 0x89, 0x92, 0xbf, 0xe0, 0x98, 0xff, 0x17, - 0x08, 0xae, 0x83, 0xc2, 0x09, 0xe9, 0x57, 0x96, 0xe4, 0x96, 0x30, 0xd1, 0x3d, 0x00, 0x27, 0x63, - 0x29, 0x76, 0x19, 0x14, 0x7b, 0x38, 0x4c, 0x89, 0x0a, 0x92, 0x39, 0x8a, 0x4e, 0xc6, 0xb7, 0xc4, - 0x61, 0x38, 0x86, 0x6f, 0x81, 0x12, 0x23, 0x91, 0x47, 0xc6, 0x54, 0xe5, 0xcd, 0x26, 0xb5, 0x34, - 0x27, 0xa9, 0x32, 0x28, 0x06, 0x51, 0x9c, 0xf2, 0x4a, 0x41, 0xde, 0x34, 0x73, 0xd0, 0xdb, 0x71, - 0x4d, 0x24, 0x46, 0xe5, 0x65, 0x82, 0xe5, 0x44, 0xd9, 0xaa, 0x2e, 0x97, 0x3e, 0xdc, 0x06, 0xcb, - 0x29, 0x23, 0xde, 0xb1, 0x8f, 0x99, 0xc4, 0x18, 0xee, 0x35, 0xe1, 0x3f, 0xc6, 0x0c, 0x36, 0x80, - 0x11, 0x52, 0x9f, 0x55, 0x0a, 0xd5, 0xc2, 0xde, 0x6a, 0x63, 0xd3, 0x9e, 0x1e, 0x0d, 0xfb, 0x88, - 0xfa, 0xcd, 0x95, 0xc1, 0xb7, 0x1d, 0xed, 0xfc, 0xd7, 0xe7, 0x9a, 0xee, 0x4a, 0x2d, 0x2a, 0xab, - 0xc2, 0x3c, 0xc3, 0x09, 0xee, 0x30, 0x75, 0x51, 0xf4, 0x14, 0x6c, 0x4e, 0xad, 0x2a, 0xf6, 0x01, - 0x28, 0xc5, 0x72, 0x45, 0x66, 0xb5, 0xda, 0xd8, 0xca, 0x23, 0x32, 0x7d, 0xd3, 0x10, 0x14, 0x57, - 0x69, 0x1b, 0x7f, 0x0a, 0xa0, 0x28, 0xa3, 0xc1, 0x37, 0xc0, 0x10, 0xbd, 0x87, 0xd5, 0xfc, 0xb9, - 0xfc, 0x3c, 0x99, 0xb7, 0x16, 0x28, 0xb2, 0x64, 0x50, 0xfd, 0xdd, 0x97, 0x9f, 0x1f, 0x97, 0xee, - 0xc0, 0xdb, 0x4e, 0x6e, 0x56, 0xc5, 0x08, 0x31, 0xe7, 0x74, 0xaa, 0x23, 0x67, 0xf0, 0xbd, 0x0e, - 0x8a, 0xb2, 0xfb, 0x70, 0x7e, 0xec, 0xc9, 0x29, 0x33, 0xd1, 0x22, 0x89, 0xe2, 0x1f, 0x48, 0xbe, - 0x0d, 0xef, 0xe6, 0xf9, 0x4c, 0xc8, 0x66, 0x12, 0x70, 0x4e, 0x4f, 0x48, 0xff, 0x0c, 0x86, 0xc0, - 0x10, 0xad, 0xbe, 0xaa, 0x04, 0xff, 0x86, 0xed, 0xaa, 0x12, 0x4c, 0xcc, 0x09, 0xda, 0x91, 0x29, - 0x6c, 0x1f, 0xea, 0x35, 0x54, 0x9e, 0xa9, 0x82, 0xa0, 0x74, 0x41, 0x29, 0x6b, 0x09, 0x9c, 0x7f, - 0xa3, 0xa9, 0xae, 0x9b, 0xbb, 0x0b, 0x35, 0x8a, 0x69, 0x49, 0x66, 0x05, 0x6e, 0xe5, 0x81, 0x59, - 0xb7, 0x9b, 0x47, 0x83, 0x1f, 0x96, 0x76, 0x3e, 0xb4, 0xb4, 0xc1, 0xd0, 0xd2, 0x2f, 0x86, 0x96, - 0xfe, 0x7d, 0x68, 0xe9, 0x1f, 0x46, 0x96, 0x76, 0x31, 0xb2, 0xb4, 0xaf, 0x23, 0x4b, 0x7b, 0x59, - 0xf3, 0x03, 0xfe, 0x2a, 0x6d, 0xd9, 0x6d, 0xda, 0x71, 0x82, 0x28, 0xe0, 0x01, 0xae, 0x87, 0xb8, - 0xc5, 0x2e, 0xe3, 0xbd, 0x96, 0x11, 0xe5, 0x8b, 0xd3, 0x2a, 0xc9, 0x27, 0xe7, 0xfe, 0xdf, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x63, 0xa3, 0x8c, 0x08, 0x03, 0x05, 0x00, 0x00, + // 724 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x95, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xc7, 0xe3, 0xe6, 0xa3, 0xed, 0xb6, 0xa0, 0x76, 0x1b, 0x55, 0xa9, 0x85, 0x9c, 0xb0, 0xe5, + 0xa3, 0x8a, 0x68, 0xdc, 0x86, 0x4a, 0x45, 0xbd, 0x11, 0x90, 0x90, 0xa0, 0x07, 0x08, 0x37, 0x2e, + 0xd5, 0x26, 0x5e, 0x19, 0xab, 0x8e, 0x37, 0xf5, 0x3a, 0x11, 0xa1, 0x6a, 0x0f, 0x88, 0x07, 0x40, + 0xf0, 0x02, 0x1c, 0x38, 0xf4, 0xc8, 0x63, 0xf4, 0x58, 0x89, 0x0b, 0x27, 0x04, 0x29, 0x12, 0x3c, + 0x06, 0xda, 0xf5, 0xb8, 0x8d, 0x9d, 0x0f, 0x95, 0x43, 0xa2, 0x9d, 0xdd, 0x99, 0xf9, 0xfd, 0x77, + 0x3c, 0x63, 0x23, 0xbd, 0xe5, 0x78, 0x0e, 0xeb, 0xb6, 0x4c, 0xf9, 0xeb, 0x6e, 0x9a, 0x07, 0x1d, + 0xe6, 0xf7, 0x2a, 0x6d, 0x9f, 0x07, 0x1c, 0x5f, 0x87, 0xb3, 0x8a, 0xfc, 0x75, 0x37, 0xf5, 0x45, + 0xda, 0x72, 0x3c, 0x6e, 0xaa, 0xff, 0xd0, 0x45, 0xcf, 0xdb, 0xdc, 0xe6, 0x6a, 0x69, 0xca, 0x15, + 0xec, 0xde, 0xb0, 0x39, 0xb7, 0x5d, 0x66, 0xd2, 0xb6, 0x63, 0x52, 0xcf, 0xe3, 0x01, 0x0d, 0x1c, + 0xee, 0x09, 0x38, 0x4d, 0x22, 0x83, 0x5e, 0x9b, 0xc1, 0x19, 0xd9, 0x46, 0x0b, 0x2f, 0xa4, 0x82, + 0x47, 0xdc, 0x62, 0x75, 0x76, 0xd0, 0x61, 0x22, 0xc0, 0xab, 0xe8, 0x5a, 0x93, 0x7b, 0x81, 0x4f, + 0x9b, 0xc1, 0x1e, 0xb5, 0x2c, 0xbf, 0xa0, 0x95, 0xb4, 0xb5, 0xd9, 0xfa, 0x7c, 0xb4, 0xf9, 0xd0, + 0xb2, 0x7c, 0xb2, 0x8e, 0x16, 0x07, 0x02, 0x45, 0x9b, 0x7b, 0x82, 0x61, 0x8c, 0x32, 0x4d, 0x6e, + 0x31, 0x15, 0x30, 0x5f, 0x57, 0xeb, 0x9d, 0xcc, 0xdf, 0xcf, 0x45, 0x8d, 0x3c, 0x05, 0xf7, 0x97, + 0x01, 0x0d, 0xfe, 0x0b, 0x84, 0x17, 0x50, 0x7a, 0x9f, 0xf5, 0x0a, 0x53, 0xea, 0x48, 0x2e, 0xc9, + 0x06, 0xc2, 0x83, 0xb9, 0x80, 0x9d, 0x47, 0xd9, 0x2e, 0x75, 0x3b, 0x0c, 0x92, 0x84, 0x06, 0xd0, + 0x59, 0x74, 0x4b, 0xea, 0xba, 0x11, 0x7c, 0x19, 0xe5, 0x04, 0xf3, 0x2c, 0x16, 0x51, 0xc1, 0x1a, + 0x16, 0x35, 0x35, 0x42, 0x54, 0x1e, 0x65, 0x1d, 0xaf, 0xdd, 0x09, 0x0a, 0xe9, 0x10, 0xa6, 0x0c, + 0x72, 0x1c, 0xd5, 0x44, 0x61, 0x40, 0x97, 0x8e, 0x66, 0x7c, 0x58, 0x03, 0xe9, 0xc2, 0xc6, 0x2b, + 0x68, 0xa6, 0x23, 0x98, 0xb5, 0x67, 0x53, 0xa1, 0x30, 0x99, 0xfa, 0xb4, 0xb4, 0x9f, 0x50, 0x81, + 0xab, 0x28, 0xe3, 0x72, 0x5b, 0x14, 0xd2, 0xa5, 0xf4, 0xda, 0x5c, 0x75, 0xa9, 0x12, 0x6f, 0x8d, + 0xca, 0x2e, 0xb7, 0x6b, 0xb3, 0xa7, 0x3f, 0x8a, 0xa9, 0x93, 0x3f, 0x5f, 0xcb, 0x5a, 0x5d, 0xf9, + 0x92, 0x6d, 0x54, 0x84, 0x67, 0x72, 0x29, 0xb5, 0xd6, 0x7b, 0xcc, 0x3c, 0xde, 0x8a, 0x6e, 0x9d, + 0x47, 0x59, 0x4b, 0xda, 0x51, 0x95, 0x94, 0x41, 0x6a, 0xa8, 0x34, 0x3e, 0x10, 0xb4, 0x16, 0xd0, + 0xb4, 0x2c, 0x07, 0x13, 0x02, 0x62, 0x23, 0x13, 0x6a, 0xfc, 0x00, 0x2e, 0x1f, 0xc3, 0x5d, 0xa9, + 0x95, 0xa2, 0xe7, 0x19, 0xe7, 0x8d, 0x54, 0x0a, 0xac, 0x3c, 0x44, 0x3c, 0xa7, 0x3e, 0x6d, 0x09, + 0x80, 0x91, 0x67, 0x68, 0x29, 0xb6, 0x0b, 0x89, 0xb6, 0x50, 0xae, 0xad, 0x76, 0x54, 0xa6, 0xb9, + 0xea, 0x72, 0xb2, 0x96, 0xa1, 0x7f, 0x2d, 0x23, 0xcb, 0x59, 0x07, 0xdf, 0xea, 0xc7, 0x1c, 0xca, + 0xaa, 0x6c, 0xf8, 0x2d, 0xca, 0xc8, 0x26, 0xc7, 0xa5, 0x64, 0x5c, 0x72, 0x70, 0xf4, 0x9b, 0x13, + 0x3c, 0x42, 0x31, 0x64, 0xfd, 0xdd, 0xb7, 0xdf, 0x9f, 0xa6, 0xee, 0xe2, 0xdb, 0x66, 0x62, 0x28, + 0xe5, 0xac, 0x08, 0xf3, 0x30, 0x56, 0xad, 0x23, 0xfc, 0x5e, 0x43, 0x59, 0xd5, 0xe6, 0x78, 0x74, + 0xee, 0xc1, 0x71, 0xd2, 0xc9, 0x24, 0x17, 0xe0, 0x6f, 0x29, 0x7e, 0x05, 0xdf, 0x4b, 0xf2, 0x85, + 0x74, 0x1b, 0x12, 0x60, 0x1e, 0xee, 0xb3, 0xde, 0x11, 0xfe, 0xa2, 0xa1, 0xa5, 0x11, 0xbd, 0x81, + 0xcd, 0x31, 0x17, 0x1e, 0xd7, 0x7e, 0xfa, 0xc6, 0xd5, 0x03, 0x40, 0x70, 0x59, 0x09, 0xbe, 0x85, + 0xc9, 0x70, 0xc1, 0xc2, 0x20, 0x61, 0x36, 0x7a, 0x7b, 0xaa, 0x39, 0xf0, 0x31, 0xca, 0x86, 0xba, + 0x46, 0x17, 0x2b, 0xa6, 0x84, 0x4c, 0x72, 0x01, 0x76, 0x45, 0xb1, 0xd7, 0xf0, 0x9d, 0x24, 0x5b, + 0xe1, 0x86, 0x9f, 0x96, 0x8b, 0x32, 0x72, 0xf4, 0xc7, 0x75, 0xca, 0xe5, 0xcb, 0x67, 0x5c, 0xa7, + 0x0c, 0xbc, 0x37, 0x48, 0x51, 0xc1, 0x57, 0x76, 0xb4, 0x32, 0xc9, 0x0f, 0xdd, 0x5d, 0x52, 0x0e, + 0x50, 0x2e, 0xec, 0x5c, 0x3c, 0xfa, 0x2e, 0xb1, 0xe1, 0xd0, 0x57, 0x27, 0xfa, 0x00, 0xd3, 0x50, + 0xcc, 0x02, 0x5e, 0x4e, 0x02, 0xc3, 0xa1, 0xa8, 0xed, 0x9e, 0xfe, 0x32, 0x52, 0x27, 0x7d, 0x23, + 0x75, 0xda, 0x37, 0xb4, 0xb3, 0xbe, 0xa1, 0xfd, 0xec, 0x1b, 0xda, 0x87, 0x73, 0x23, 0x75, 0x76, + 0x6e, 0xa4, 0xbe, 0x9f, 0x1b, 0xa9, 0x57, 0x65, 0xdb, 0x09, 0x5e, 0x77, 0x1a, 0x95, 0x26, 0x6f, + 0x99, 0x8e, 0xe7, 0x04, 0x0e, 0x5d, 0x77, 0x69, 0x43, 0x5c, 0xe4, 0x7b, 0xa3, 0x32, 0xaa, 0x2f, + 0x50, 0x23, 0xa7, 0x3e, 0x41, 0xf7, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x52, 0xf4, 0x54, 0x5c, + 0x13, 0x07, 0x00, 0x00, } func (this *QueryCodeResponse) Equal(that interface{}) bool { @@ -456,6 +627,54 @@ func (this *QueryStateResponse) Equal(that interface{}) bool { } return true } +func (this *QueryContractAddrByDenomResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryContractAddrByDenomResponse) + if !ok { + that2, ok := that.(QueryContractAddrByDenomResponse) + 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 *QueryDenomResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryDenomResponse) + if !ok { + that2, ok := that.(QueryDenomResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom != that1.Denom { + return false + } + return true +} // Reference imports to suppress errors if they are not otherwise used. var _ context.Context @@ -473,6 +692,8 @@ type QueryClient interface { Code(ctx context.Context, in *QueryCodeRequest, opts ...grpc.CallOption) (*QueryCodeResponse, error) // State gets the state bytes of the given address and key bytes. State(ctx context.Context, in *QueryStateRequest, opts ...grpc.CallOption) (*QueryStateResponse, error) + ContractAddrByDenom(ctx context.Context, in *QueryContractAddrByDenomRequest, opts ...grpc.CallOption) (*QueryContractAddrByDenomResponse, error) + Denom(ctx context.Context, in *QueryDenomRequest, opts ...grpc.CallOption) (*QueryDenomResponse, error) // Call execute entry function and return the function result Call(ctx context.Context, in *QueryCallRequest, opts ...grpc.CallOption) (*QueryCallResponse, error) // Params queries all parameters. @@ -505,6 +726,24 @@ func (c *queryClient) State(ctx context.Context, in *QueryStateRequest, opts ... 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...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Denom(ctx context.Context, in *QueryDenomRequest, opts ...grpc.CallOption) (*QueryDenomResponse, error) { + out := new(QueryDenomResponse) + err := c.cc.Invoke(ctx, "/minievm.evm.v1.Query/Denom", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Call(ctx context.Context, in *QueryCallRequest, opts ...grpc.CallOption) (*QueryCallResponse, error) { out := new(QueryCallResponse) err := c.cc.Invoke(ctx, "/minievm.evm.v1.Query/Call", in, out, opts...) @@ -529,6 +768,8 @@ type QueryServer interface { Code(context.Context, *QueryCodeRequest) (*QueryCodeResponse, error) // State gets the state bytes of the given address and key bytes. State(context.Context, *QueryStateRequest) (*QueryStateResponse, error) + ContractAddrByDenom(context.Context, *QueryContractAddrByDenomRequest) (*QueryContractAddrByDenomResponse, error) + Denom(context.Context, *QueryDenomRequest) (*QueryDenomResponse, error) // Call execute entry function and return the function result Call(context.Context, *QueryCallRequest) (*QueryCallResponse, error) // Params queries all parameters. @@ -545,6 +786,12 @@ func (*UnimplementedQueryServer) Code(ctx context.Context, req *QueryCodeRequest func (*UnimplementedQueryServer) State(ctx context.Context, req *QueryStateRequest) (*QueryStateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method State not implemented") } +func (*UnimplementedQueryServer) ContractAddrByDenom(ctx context.Context, req *QueryContractAddrByDenomRequest) (*QueryContractAddrByDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ContractAddrByDenom not implemented") +} +func (*UnimplementedQueryServer) Denom(ctx context.Context, req *QueryDenomRequest) (*QueryDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Denom not implemented") +} func (*UnimplementedQueryServer) Call(ctx context.Context, req *QueryCallRequest) (*QueryCallResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Call not implemented") } @@ -592,6 +839,42 @@ func _Query_State_Handler(srv interface{}, ctx context.Context, dec func(interfa 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 { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ContractAddrByDenom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/minievm.evm.v1.Query/ContractAddrByDenom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ContractAddrByDenom(ctx, req.(*QueryContractAddrByDenomRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Denom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Denom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/minievm.evm.v1.Query/Denom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Denom(ctx, req.(*QueryDenomRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryCallRequest) if err := dec(in); err != nil { @@ -640,6 +923,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "State", Handler: _Query_State_Handler, }, + { + MethodName: "ContractAddrByDenom", + Handler: _Query_ContractAddrByDenom_Handler, + }, + { + MethodName: "Denom", + Handler: _Query_Denom_Handler, + }, { MethodName: "Call", Handler: _Query_Call_Handler, @@ -873,7 +1164,7 @@ func (m *QueryCallResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryContractAddrByDenomRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -883,20 +1174,27 @@ func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryContractAddrByDenomRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryContractAddrByDenomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } -func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryContractAddrByDenomResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -906,62 +1204,175 @@ func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryContractAddrByDenomResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryContractAddrByDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) + 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 } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *QueryDenomRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *QueryCodeRequest) Size() (n int) { - if m == nil { - return 0 - } + +func (m *QueryDenomRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.ContractAddr) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + if len(m.ContractAddr) > 0 { + i -= len(m.ContractAddr) + copy(dAtA[i:], m.ContractAddr) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ContractAddr))) + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryCodeResponse) Size() (n int) { - if m == nil { - return 0 +func (m *QueryDenomResponse) 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 *QueryDenomResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.Code) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryCodeRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ContractAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryCodeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Code) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) } return n } @@ -1039,6 +1450,58 @@ func (m *QueryCallResponse) Size() (n int) { return n } +func (m *QueryContractAddrByDenomRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryContractAddrByDenomResponse) 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 *QueryDenomRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ContractAddr) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func (m *QueryParamsRequest) Size() (n int) { if m == nil { return 0 @@ -1524,7 +1987,7 @@ func (m *QueryCallRequest) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Input", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1534,25 +1997,23 @@ func (m *QueryCallRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Input = append(m.Input[:0], dAtA[iNdEx:postIndex]...) - if m.Input == nil { - m.Input = []byte{} - } + m.Input = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1608,7 +2069,7 @@ func (m *QueryCallResponse) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Response", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1618,25 +2079,23 @@ func (m *QueryCallResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Response = append(m.Response[:0], dAtA[iNdEx:postIndex]...) - if m.Response == nil { - m.Response = []byte{} - } + m.Response = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 0 { @@ -1712,6 +2171,334 @@ func (m *QueryCallResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryContractAddrByDenomRequest) 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: QueryContractAddrByDenomRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryContractAddrByDenomRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", 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.Denom = 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 *QueryContractAddrByDenomResponse) 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: QueryContractAddrByDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryContractAddrByDenomResponse: 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 *QueryDenomRequest) 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: QueryDenomRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddr", 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.ContractAddr = 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 *QueryDenomResponse) 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: QueryDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", 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.Denom = 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 *QueryParamsRequest) 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 b2ac6b9..8a9d5b3 100644 --- a/x/evm/types/query.pb.gw.go +++ b/x/evm/types/query.pb.gw.go @@ -163,6 +163,96 @@ func local_request_Query_State_0(ctx context.Context, marshaler runtime.Marshale } +var ( + filter_Query_ContractAddrByDenom_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_ContractAddrByDenom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryContractAddrByDenomRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ContractAddrByDenom_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ContractAddrByDenom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ContractAddrByDenom_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryContractAddrByDenomRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ContractAddrByDenom_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ContractAddrByDenom(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Denom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["contract_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "contract_addr") + } + + protoReq.ContractAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "contract_addr", err) + } + + msg, err := client.Denom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Denom_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["contract_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "contract_addr") + } + + protoReq.ContractAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "contract_addr", err) + } + + msg, err := server.Denom(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Call_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCallRequest var metadata runtime.ServerMetadata @@ -267,6 +357,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + 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() + 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_ContractAddrByDenom_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_ContractAddrByDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Denom_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_Denom_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_Denom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_Query_Call_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -394,6 +530,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + 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() + 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_ContractAddrByDenom_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_ContractAddrByDenom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Denom_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_Denom_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_Denom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_Query_Call_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -442,6 +618,10 @@ var ( pattern_Query_State_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"minievm", "evm", "v1", "states", "contract_addr", "key"}, "", 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))) + pattern_Query_Call_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"minievm", "evm", "v1", "call"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"minievm", "evm", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) @@ -452,6 +632,10 @@ var ( forward_Query_State_0 = runtime.ForwardResponseMessage + forward_Query_ContractAddrByDenom_0 = runtime.ForwardResponseMessage + + forward_Query_Denom_0 = runtime.ForwardResponseMessage + forward_Query_Call_0 = runtime.ForwardResponseMessage forward_Query_Params_0 = runtime.ForwardResponseMessage diff --git a/x/evm/types/tx.pb.go b/x/evm/types/tx.pb.go index 43e1ad2..708913b 100644 --- a/x/evm/types/tx.pb.go +++ b/x/evm/types/tx.pb.go @@ -36,8 +36,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgCreate struct { // Sender is the that actor that signed the messages Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` - // Code is raw contract bytes code. - Code []byte `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` + // Code is hex encoded raw contract bytes code. + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` } func (m *MsgCreate) Reset() { *m = MsgCreate{} } @@ -80,17 +80,17 @@ func (m *MsgCreate) GetSender() string { return "" } -func (m *MsgCreate) GetCode() []byte { +func (m *MsgCreate) GetCode() string { if m != nil { return m.Code } - return nil + return "" } // MsgCreateResponse defines the Msg/Create response type. type MsgCreateResponse struct { - Result []byte `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - // hex encoded contract address + Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + // hex encoded address (0x prefixed) ContractAddr string `protobuf:"bytes,2,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` } @@ -127,11 +127,11 @@ func (m *MsgCreateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgCreateResponse proto.InternalMessageInfo -func (m *MsgCreateResponse) GetResult() []byte { +func (m *MsgCreateResponse) GetResult() string { if m != nil { return m.Result } - return nil + return "" } func (m *MsgCreateResponse) GetContractAddr() string { @@ -146,10 +146,10 @@ type MsgCall struct { // Sender is the that actor that signed the messages Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` // ContractAddr is the contract address to be executed. - // It can be cosmos address or hex encoded address. + // It can be cosmos address or hex encoded address (0x prefixed). ContractAddr string `protobuf:"bytes,2,opt,name=contract_addr,json=contractAddr,proto3" json:"contract_addr,omitempty"` - // Execution input bytes. - Input []byte `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` + // Hex encoded execution input bytes. + Input string `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` } func (m *MsgCall) Reset() { *m = MsgCall{} } @@ -199,16 +199,16 @@ func (m *MsgCall) GetContractAddr() string { return "" } -func (m *MsgCall) GetInput() []byte { +func (m *MsgCall) GetInput() string { if m != nil { return m.Input } - return nil + return "" } // MsgCallResponse defines the Msg/Call response type. type MsgCallResponse struct { - Result []byte `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` Logs []Log `protobuf:"bytes,2,rep,name=logs,proto3" json:"logs"` } @@ -245,11 +245,11 @@ func (m *MsgCallResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgCallResponse proto.InternalMessageInfo -func (m *MsgCallResponse) GetResult() []byte { +func (m *MsgCallResponse) GetResult() string { if m != nil { return m.Result } - return nil + return "" } func (m *MsgCallResponse) GetLogs() []Log { @@ -367,41 +367,41 @@ func init() { func init() { proto.RegisterFile("minievm/evm/v1/tx.proto", fileDescriptor_d925564029372f6a) } var fileDescriptor_d925564029372f6a = []byte{ - // 538 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x41, 0x6b, 0x13, 0x41, - 0x14, 0xce, 0x34, 0x69, 0x24, 0x93, 0xb4, 0xd2, 0x31, 0x34, 0xc9, 0x8a, 0xdb, 0xb8, 0x1e, 0x0c, - 0x81, 0x66, 0x6d, 0x04, 0xc1, 0x9c, 0x34, 0x8a, 0x27, 0x0b, 0x65, 0x45, 0x10, 0x41, 0xca, 0x24, - 0x3b, 0x4c, 0x07, 0x76, 0x77, 0x96, 0x99, 0x49, 0x68, 0x6f, 0xe2, 0xd1, 0x93, 0xa0, 0x3f, 0xc2, - 0x63, 0x0e, 0xfe, 0x88, 0x1e, 0x8b, 0x27, 0x4f, 0x22, 0xc9, 0x21, 0x57, 0x7f, 0x82, 0xec, 0xec, - 0x24, 0x6d, 0x97, 0x96, 0x48, 0x0f, 0x1b, 0xe6, 0xcd, 0xfb, 0xde, 0xf7, 0xbd, 0xef, 0x65, 0x1e, - 0xac, 0x85, 0x2c, 0x62, 0x64, 0x1c, 0xba, 0xc9, 0x37, 0xde, 0x73, 0xd5, 0x71, 0x27, 0x16, 0x5c, - 0x71, 0xb4, 0x69, 0x12, 0x9d, 0xe4, 0x1b, 0xef, 0x59, 0x5b, 0x38, 0x64, 0x11, 0x77, 0xf5, 0x6f, - 0x0a, 0xb1, 0x6a, 0x43, 0x2e, 0x43, 0x2e, 0xdd, 0x50, 0xd2, 0xa4, 0x34, 0x94, 0xd4, 0x24, 0x1a, - 0x69, 0xe2, 0x50, 0x47, 0x6e, 0x1a, 0x98, 0x54, 0x95, 0x72, 0xca, 0xd3, 0xfb, 0xe4, 0x64, 0x6e, - 0xad, 0x6c, 0x17, 0x27, 0x31, 0x31, 0x15, 0x4e, 0x0c, 0x4b, 0xfb, 0x92, 0xbe, 0x10, 0x04, 0x2b, - 0x82, 0x1e, 0xc1, 0xa2, 0x24, 0x91, 0x4f, 0x44, 0x1d, 0x34, 0x41, 0xab, 0xd4, 0xaf, 0xff, 0xfc, - 0xb1, 0x5b, 0x35, 0x02, 0xcf, 0x7d, 0x5f, 0x10, 0x29, 0xdf, 0x28, 0xc1, 0x22, 0xea, 0x19, 0x1c, - 0x42, 0xb0, 0x30, 0xe4, 0x3e, 0xa9, 0xaf, 0x35, 0x41, 0xab, 0xe2, 0xe9, 0x73, 0xef, 0xde, 0xa7, - 0xf9, 0xa4, 0x6d, 0x00, 0x9f, 0xe7, 0x93, 0xf6, 0x46, 0x22, 0xbb, 0x14, 0x71, 0x0e, 0xe0, 0xd6, - 0x32, 0xf0, 0x88, 0x8c, 0x79, 0x24, 0x09, 0xda, 0x86, 0x45, 0x41, 0xe4, 0x28, 0x50, 0x5a, 0xb9, - 0xe2, 0x99, 0x08, 0x3d, 0x80, 0x1b, 0x43, 0x1e, 0x29, 0x81, 0x87, 0xea, 0x10, 0xfb, 0xbe, 0xd0, - 0x42, 0x25, 0xaf, 0xb2, 0xb8, 0x4c, 0xba, 0x72, 0xbe, 0x02, 0x78, 0x2b, 0xa1, 0xc4, 0x41, 0x70, - 0x03, 0x0b, 0xff, 0x23, 0x81, 0xaa, 0x70, 0x9d, 0x45, 0xf1, 0x48, 0xd5, 0xf3, 0xba, 0xbd, 0x34, - 0xe8, 0xdd, 0xcd, 0x38, 0x2d, 0x2f, 0x9c, 0xe2, 0x20, 0x70, 0x3e, 0xc0, 0xdb, 0xe6, 0xb8, 0xd2, - 0x65, 0x17, 0x16, 0x02, 0x4e, 0x65, 0x7d, 0xad, 0x99, 0x6f, 0x95, 0xbb, 0x77, 0x3a, 0x97, 0x1f, - 0x47, 0xe7, 0x35, 0xa7, 0xfd, 0xd2, 0xe9, 0xef, 0x9d, 0xdc, 0xf7, 0xf9, 0xa4, 0x0d, 0x3c, 0x8d, - 0x75, 0xbe, 0x01, 0xcd, 0xff, 0x36, 0xf6, 0xb1, 0x22, 0x07, 0x58, 0xe0, 0x50, 0xa2, 0x27, 0xb0, - 0x84, 0x47, 0xea, 0x88, 0x0b, 0xa6, 0x4e, 0x56, 0xfa, 0x3f, 0x87, 0xa2, 0xa7, 0xb0, 0x18, 0x6b, - 0x06, 0xed, 0xbd, 0xdc, 0xdd, 0xce, 0x76, 0x90, 0xf2, 0x5f, 0x6c, 0xc2, 0x14, 0xf4, 0x36, 0x93, - 0x11, 0x9c, 0x53, 0x39, 0x0d, 0x58, 0xcb, 0x74, 0xb5, 0x70, 0xdf, 0xfd, 0x0b, 0x60, 0x7e, 0x5f, - 0x52, 0xf4, 0x0a, 0x16, 0xcd, 0x7b, 0x6b, 0x64, 0x75, 0x96, 0x0f, 0xc3, 0xba, 0x7f, 0x6d, 0x6a, - 0x39, 0xcd, 0x67, 0xb0, 0xa0, 0xff, 0xf2, 0xda, 0x55, 0x50, 0x1c, 0x04, 0xd6, 0xce, 0x35, 0x89, - 0x25, 0xc3, 0x3b, 0x58, 0xb9, 0x34, 0xbf, 0xab, 0x0a, 0x2e, 0x02, 0xac, 0x87, 0x2b, 0x00, 0x0b, - 0x66, 0x6b, 0xfd, 0x63, 0x32, 0xa5, 0xfe, 0xcb, 0xd3, 0xa9, 0x0d, 0xce, 0xa6, 0x36, 0xf8, 0x33, - 0xb5, 0xc1, 0x97, 0x99, 0x9d, 0x3b, 0x9b, 0xd9, 0xb9, 0x5f, 0x33, 0x3b, 0xf7, 0xbe, 0x4d, 0x99, - 0x3a, 0x1a, 0x0d, 0x3a, 0x43, 0x1e, 0xba, 0x2c, 0x62, 0x8a, 0xe1, 0xdd, 0x00, 0x0f, 0xa4, 0xbb, - 0x58, 0xd5, 0x63, 0xbd, 0xac, 0x7a, 0x53, 0x07, 0x45, 0xbd, 0xaa, 0x8f, 0xff, 0x05, 0x00, 0x00, - 0xff, 0xff, 0xd2, 0xa4, 0x6b, 0xbe, 0x4e, 0x04, 0x00, 0x00, + // 535 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xc1, 0x6b, 0x13, 0x4f, + 0x14, 0xce, 0x36, 0x69, 0x7e, 0x64, 0xd2, 0xf6, 0x47, 0xc7, 0xd0, 0x24, 0x2b, 0x6e, 0xeb, 0x7a, + 0xb0, 0x04, 0x9a, 0xb5, 0x11, 0x04, 0x73, 0xd2, 0x28, 0x9e, 0x2c, 0x94, 0x88, 0x20, 0x82, 0x94, + 0xc9, 0xee, 0x30, 0x1d, 0xd8, 0xdd, 0x59, 0x66, 0x26, 0xa1, 0xbd, 0x89, 0x47, 0x4f, 0x82, 0xfe, + 0x11, 0x1e, 0x73, 0xf0, 0x8f, 0xe8, 0xb1, 0x78, 0xf2, 0x24, 0x92, 0x1c, 0x72, 0xf5, 0x4f, 0x90, + 0x99, 0x9d, 0xdd, 0xb6, 0x4b, 0x4b, 0xc4, 0xc3, 0x86, 0x79, 0xf3, 0xbe, 0xf7, 0x7d, 0xef, 0x7b, + 0x99, 0x07, 0x9a, 0x11, 0x8d, 0x29, 0x9e, 0x44, 0x9e, 0xfa, 0x26, 0xfb, 0x9e, 0x3c, 0xe9, 0x26, + 0x9c, 0x49, 0x06, 0x37, 0x4c, 0xa2, 0xab, 0xbe, 0xc9, 0xbe, 0xbd, 0x89, 0x22, 0x1a, 0x33, 0x4f, + 0xff, 0xa6, 0x10, 0xbb, 0xe9, 0x33, 0x11, 0x31, 0xe1, 0x45, 0x82, 0xa8, 0xd2, 0x48, 0x10, 0x93, + 0x68, 0xa7, 0x89, 0x23, 0x1d, 0x79, 0x69, 0x60, 0x52, 0x0d, 0xc2, 0x08, 0x4b, 0xef, 0xd5, 0xc9, + 0xdc, 0xda, 0xc5, 0x2e, 0x4e, 0x13, 0x6c, 0x2a, 0xdc, 0x04, 0xd4, 0x0e, 0x04, 0x79, 0xc6, 0x31, + 0x92, 0x18, 0x3e, 0x00, 0x55, 0x81, 0xe3, 0x00, 0xf3, 0x96, 0xb5, 0x63, 0xed, 0xd6, 0x06, 0xad, + 0xef, 0xdf, 0xf6, 0x1a, 0x46, 0xe0, 0x69, 0x10, 0x70, 0x2c, 0xc4, 0x2b, 0xc9, 0x69, 0x4c, 0x86, + 0x06, 0x07, 0x21, 0xa8, 0xf8, 0x2c, 0xc0, 0xad, 0x15, 0x85, 0x1f, 0xea, 0x73, 0xff, 0xce, 0x87, + 0xc5, 0xb4, 0x63, 0x00, 0x1f, 0x17, 0xd3, 0xce, 0xba, 0x92, 0xcd, 0x45, 0xdc, 0x43, 0xb0, 0x99, + 0x07, 0x43, 0x2c, 0x12, 0x16, 0x0b, 0x0c, 0xb7, 0x40, 0x95, 0x63, 0x31, 0x0e, 0x65, 0xaa, 0x3c, + 0x34, 0x11, 0xbc, 0x07, 0xd6, 0x7d, 0x16, 0x4b, 0x8e, 0x7c, 0x79, 0x84, 0x82, 0x80, 0x1b, 0xa1, + 0xb5, 0xec, 0x52, 0x75, 0xe5, 0x7e, 0xb6, 0xc0, 0x7f, 0x8a, 0x12, 0x85, 0xe1, 0x3f, 0x58, 0xf8, + 0x1b, 0x09, 0xd8, 0x00, 0xab, 0x34, 0x4e, 0xc6, 0xb2, 0x55, 0xd6, 0xc9, 0x34, 0xe8, 0xdf, 0x2e, + 0x38, 0xad, 0x67, 0x4e, 0x51, 0x18, 0xba, 0xef, 0xc0, 0xff, 0xe6, 0xb8, 0xd4, 0x65, 0x0f, 0x54, + 0x42, 0x46, 0x44, 0x6b, 0x65, 0xa7, 0xbc, 0x5b, 0xef, 0xdd, 0xea, 0x5e, 0x7d, 0x1c, 0xdd, 0x97, + 0x8c, 0x0c, 0x6a, 0x67, 0x3f, 0xb7, 0x4b, 0x5f, 0x17, 0xd3, 0x8e, 0x35, 0xd4, 0x58, 0xf7, 0x8b, + 0xa5, 0xf9, 0x5f, 0x27, 0x01, 0x92, 0xf8, 0x10, 0x71, 0x14, 0x09, 0xf8, 0x08, 0xd4, 0xd0, 0x58, + 0x1e, 0x33, 0x4e, 0xe5, 0xe9, 0x52, 0xff, 0x17, 0x50, 0xf8, 0x18, 0x54, 0x13, 0xcd, 0xa0, 0xbd, + 0xd7, 0x7b, 0x5b, 0xc5, 0x0e, 0x52, 0xfe, 0xcb, 0x4d, 0x98, 0x82, 0xfe, 0x86, 0x1a, 0xc1, 0x05, + 0x95, 0xdb, 0x06, 0xcd, 0x42, 0x57, 0x99, 0xfb, 0xde, 0x6f, 0x0b, 0x94, 0x0f, 0x04, 0x81, 0x2f, + 0x40, 0xd5, 0xbc, 0xb7, 0x76, 0x51, 0x27, 0x7f, 0x18, 0xf6, 0xdd, 0x1b, 0x53, 0xf9, 0x34, 0x9f, + 0x80, 0x8a, 0xfe, 0xcb, 0x9b, 0xd7, 0x41, 0x51, 0x18, 0xda, 0xdb, 0x37, 0x24, 0x72, 0x86, 0x37, + 0x60, 0xed, 0xca, 0xfc, 0xae, 0x2b, 0xb8, 0x0c, 0xb0, 0xef, 0x2f, 0x01, 0x64, 0xcc, 0xf6, 0xea, + 0x7b, 0x35, 0xa5, 0xc1, 0xf3, 0xb3, 0x99, 0x63, 0x9d, 0xcf, 0x1c, 0xeb, 0xd7, 0xcc, 0xb1, 0x3e, + 0xcd, 0x9d, 0xd2, 0xf9, 0xdc, 0x29, 0xfd, 0x98, 0x3b, 0xa5, 0xb7, 0x1d, 0x42, 0xe5, 0xf1, 0x78, + 0xd4, 0xf5, 0x59, 0xe4, 0xd1, 0x98, 0x4a, 0x8a, 0xf6, 0x42, 0x34, 0x12, 0x5e, 0xb6, 0xaa, 0x27, + 0x7a, 0x59, 0xf5, 0xa6, 0x8e, 0xaa, 0x7a, 0x55, 0x1f, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0xc7, + 0x2b, 0x8c, 0xd8, 0x4e, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -969,7 +969,7 @@ func (m *MsgCreate) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -979,25 +979,23 @@ func (m *MsgCreate) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Code = append(m.Code[:0], dAtA[iNdEx:postIndex]...) - if m.Code == nil { - m.Code = []byte{} - } + m.Code = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1053,7 +1051,7 @@ func (m *MsgCreateResponse) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1063,25 +1061,23 @@ func (m *MsgCreateResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Result = append(m.Result[:0], dAtA[iNdEx:postIndex]...) - if m.Result == nil { - m.Result = []byte{} - } + m.Result = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { @@ -1233,7 +1229,7 @@ func (m *MsgCall) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Input", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1243,25 +1239,23 @@ func (m *MsgCall) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Input = append(m.Input[:0], dAtA[iNdEx:postIndex]...) - if m.Input == nil { - m.Input = []byte{} - } + m.Input = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1317,7 +1311,7 @@ func (m *MsgCallResponse) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1327,25 +1321,23 @@ func (m *MsgCallResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Result = append(m.Result[:0], dAtA[iNdEx:postIndex]...) - if m.Result == nil { - m.Result = []byte{} - } + m.Result = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { diff --git a/x/evm/types/types.pb.go b/x/evm/types/types.pb.go index dfe283c..bafd948 100644 --- a/x/evm/types/types.pb.go +++ b/x/evm/types/types.pb.go @@ -4,7 +4,6 @@ package types import ( - bytes "bytes" fmt "fmt" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -74,7 +73,7 @@ type Log struct { // list of topics provided by the contract. Topics []string `protobuf:"bytes,2,rep,name=topics,proto3" json:"topics,omitempty"` // supplied by the contract, usually ABI-encoded - Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + Data string `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` } func (m *Log) Reset() { *m = Log{} } @@ -118,29 +117,29 @@ func init() { func init() { proto.RegisterFile("minievm/evm/v1/types.proto", fileDescriptor_98c9eab1c4bf0154) } var fileDescriptor_98c9eab1c4bf0154 = []byte{ - // 348 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x51, 0xb1, 0x6e, 0xf2, 0x30, - 0x18, 0x8c, 0xff, 0xfc, 0xa2, 0x8a, 0x55, 0x55, 0xc2, 0xaa, 0xda, 0x94, 0xc1, 0x41, 0x99, 0x22, - 0xa4, 0x12, 0xa1, 0x6e, 0x6c, 0x45, 0x62, 0xa8, 0xca, 0x40, 0x33, 0x76, 0x41, 0x0e, 0xb1, 0x82, - 0xa5, 0x04, 0x47, 0xb1, 0xa1, 0xf0, 0x0a, 0x9d, 0x3a, 0x76, 0x64, 0x64, 0x64, 0xeb, 0x2b, 0x30, - 0x32, 0x76, 0x42, 0x6d, 0x18, 0xe8, 0xcc, 0x13, 0x54, 0x71, 0x42, 0x3b, 0x74, 0xf8, 0xac, 0xbb, - 0xef, 0xce, 0xd2, 0xd9, 0x07, 0x6b, 0x31, 0x1b, 0x33, 0x3a, 0x8d, 0xdd, 0x7c, 0xa6, 0x2d, 0x57, - 0xce, 0x13, 0x2a, 0x9a, 0x49, 0xca, 0x25, 0x47, 0x67, 0xa5, 0xd6, 0xcc, 0x67, 0xda, 0xaa, 0x55, - 0x49, 0xcc, 0xc6, 0xdc, 0x55, 0x67, 0x61, 0xa9, 0x9d, 0x87, 0x3c, 0xe4, 0x0a, 0xba, 0x39, 0x2a, - 0xb6, 0xf6, 0x1b, 0x80, 0x95, 0x3e, 0x49, 0x49, 0x2c, 0xd0, 0x2d, 0x84, 0x74, 0x26, 0x53, 0x32, - 0xa0, 0x2c, 0x11, 0x26, 0xa8, 0xeb, 0x8e, 0xde, 0xb1, 0xb3, 0xad, 0x65, 0x74, 0xf3, 0x6d, 0xf7, - 0xae, 0x2f, 0x0e, 0x5b, 0xab, 0x3a, 0x27, 0x71, 0xd4, 0xb6, 0x7f, 0x8d, 0xb6, 0x67, 0x28, 0xd2, - 0x65, 0x89, 0x40, 0x0f, 0x10, 0x91, 0x28, 0xe2, 0x4f, 0x34, 0x18, 0x24, 0x13, 0x3f, 0x62, 0x62, - 0x44, 0x53, 0x61, 0xfe, 0xab, 0xeb, 0x8e, 0xd1, 0xb1, 0x0f, 0x5b, 0xeb, 0xaa, 0xb8, 0xfd, 0xd7, - 0x63, 0x2f, 0xf7, 0xab, 0x06, 0xf0, 0xaa, 0xa5, 0xd2, 0xff, 0x11, 0xda, 0x97, 0xaf, 0x0b, 0x4b, - 0xfb, 0x5a, 0x58, 0xe0, 0x79, 0xbf, 0x6a, 0xc0, 0xfc, 0xe9, 0x45, 0x5c, 0xfb, 0x1e, 0xea, 0x3d, - 0x1e, 0x22, 0x13, 0x9e, 0x90, 0x20, 0x48, 0xa9, 0xc8, 0x23, 0x03, 0xc7, 0xf0, 0x8e, 0x14, 0x5d, - 0xc0, 0x8a, 0xe4, 0x09, 0x1b, 0x96, 0x01, 0xbc, 0x92, 0x21, 0x04, 0xff, 0x07, 0x44, 0x12, 0x53, - 0xaf, 0x03, 0xe7, 0xd4, 0x53, 0xb8, 0xd3, 0x5b, 0x7f, 0x62, 0x6d, 0x99, 0x61, 0xb0, 0xce, 0x30, - 0xd8, 0x64, 0x18, 0x7c, 0x64, 0x18, 0xbc, 0xec, 0xb0, 0xb6, 0xd9, 0x61, 0xed, 0x7d, 0x87, 0xb5, - 0xc7, 0x46, 0xc8, 0xe4, 0x68, 0xe2, 0x37, 0x87, 0x3c, 0x76, 0xd9, 0x98, 0x49, 0x46, 0xae, 0x23, - 0xe2, 0x0b, 0xf7, 0x58, 0xca, 0x4c, 0xd5, 0xa2, 0x3a, 0xf1, 0x2b, 0xea, 0x6f, 0x6f, 0xbe, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x1d, 0xe3, 0x49, 0x73, 0xb2, 0x01, 0x00, 0x00, + // 345 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x51, 0x31, 0x6f, 0xea, 0x30, + 0x18, 0x8c, 0x5f, 0x9e, 0x78, 0x8a, 0x87, 0x27, 0x61, 0x55, 0x6d, 0xca, 0xe0, 0x20, 0x4f, 0x08, + 0xa9, 0x44, 0xa8, 0x1b, 0x5b, 0x91, 0x18, 0xaa, 0x32, 0xd0, 0x8c, 0x5d, 0x90, 0x43, 0xac, 0x60, + 0x29, 0xc1, 0x51, 0x6c, 0x28, 0xfc, 0x85, 0x4e, 0x1d, 0x3b, 0x32, 0x32, 0xb2, 0xf5, 0x2f, 0x30, + 0x32, 0x76, 0x42, 0x6d, 0x18, 0xe8, 0xcc, 0x2f, 0xa8, 0xe2, 0x84, 0x76, 0xe8, 0xf0, 0x59, 0x77, + 0xdf, 0x9d, 0xa5, 0xb3, 0x0f, 0xd6, 0x62, 0x3e, 0xe1, 0x6c, 0x16, 0xbb, 0xf9, 0xcc, 0xda, 0xae, + 0x5a, 0x24, 0x4c, 0xb6, 0x92, 0x54, 0x28, 0x81, 0xfe, 0x97, 0x5a, 0x2b, 0x9f, 0x59, 0xbb, 0x56, + 0xa5, 0x31, 0x9f, 0x08, 0x57, 0x9f, 0x85, 0xa5, 0x76, 0x16, 0x8a, 0x50, 0x68, 0xe8, 0xe6, 0xa8, + 0xd8, 0x92, 0x57, 0x00, 0x2b, 0x03, 0x9a, 0xd2, 0x58, 0xa2, 0x1b, 0x08, 0xd9, 0x5c, 0xa5, 0x74, + 0xc8, 0x78, 0x22, 0x6d, 0x50, 0x37, 0x1b, 0x66, 0x97, 0x64, 0x3b, 0xc7, 0xea, 0xe5, 0xdb, 0xde, + 0xed, 0x40, 0x1e, 0x77, 0x4e, 0x75, 0x41, 0xe3, 0xa8, 0x43, 0x7e, 0x8c, 0xc4, 0xb3, 0x34, 0xe9, + 0xf1, 0x44, 0xa2, 0x7b, 0x88, 0x68, 0x14, 0x89, 0x47, 0x16, 0x0c, 0x93, 0xa9, 0x1f, 0x71, 0x39, + 0x66, 0xa9, 0xb4, 0xff, 0xd4, 0xcd, 0x86, 0xd5, 0x25, 0xc7, 0x9d, 0x73, 0x59, 0xdc, 0xfe, 0xed, + 0x21, 0xab, 0xc3, 0xba, 0x09, 0xbc, 0x6a, 0xa9, 0x0c, 0xbe, 0x85, 0xce, 0xc5, 0xcb, 0xd2, 0x31, + 0x3e, 0x97, 0x0e, 0x78, 0x3a, 0xac, 0x9b, 0x30, 0x7f, 0x7a, 0x11, 0x97, 0xdc, 0x41, 0xb3, 0x2f, + 0x42, 0x64, 0xc3, 0x7f, 0x34, 0x08, 0x52, 0x26, 0xf3, 0xc8, 0xa0, 0x61, 0x79, 0x27, 0x8a, 0xce, + 0x61, 0x45, 0x89, 0x84, 0x8f, 0xca, 0x00, 0x5e, 0xc9, 0x10, 0x82, 0x7f, 0x03, 0xaa, 0xa8, 0x6d, + 0x6a, 0xbb, 0xc6, 0xdd, 0xfe, 0xe6, 0x03, 0x1b, 0xab, 0x0c, 0x83, 0x4d, 0x86, 0xc1, 0x36, 0xc3, + 0xe0, 0x3d, 0xc3, 0xe0, 0x79, 0x8f, 0x8d, 0xed, 0x1e, 0x1b, 0x6f, 0x7b, 0x6c, 0x3c, 0x34, 0x43, + 0xae, 0xc6, 0x53, 0xbf, 0x35, 0x12, 0xb1, 0xcb, 0x27, 0x5c, 0x71, 0x7a, 0x15, 0x51, 0x5f, 0xba, + 0xa7, 0x52, 0xe6, 0xba, 0x16, 0xdd, 0x89, 0x5f, 0xd1, 0x7f, 0x7b, 0xfd, 0x15, 0x00, 0x00, 0xff, + 0xff, 0x21, 0x97, 0xce, 0xbe, 0xb2, 0x01, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -210,7 +209,7 @@ func (this *Log) Equal(that interface{}) bool { return false } } - if !bytes.Equal(this.Data, that1.Data) { + if this.Data != that1.Data { return false } return true @@ -629,7 +628,7 @@ func (m *Log) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) } - var byteLen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -639,25 +638,23 @@ func (m *Log) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTypes } - postIndex := iNdEx + byteLen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTypes } if postIndex > l { return io.ErrUnexpectedEOF } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } + m.Data = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex