From 2c17febf74a65e7cd38108f07271d335fdc05712 Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:28:58 +0900 Subject: [PATCH] introduce blocked addrs feature --- app/app.go | 1 + app/ibc-hooks/common_test.go | 1 + x/bank/keeper/common_test.go | 1 + x/evm/contracts/counter/Counter.go | 2 +- x/evm/contracts/custom_erc20/CustomERC20.go | 25 ++- x/evm/contracts/custom_erc20/CustomERC20.sol | 73 ++++--- x/evm/contracts/erc20/ERC20.go | 67 +++++- x/evm/contracts/erc20/ERC20.sol | 67 ++++-- x/evm/contracts/erc20_acl/ERC20ACL.go | 203 ++++++++++++++++++ x/evm/contracts/erc20_acl/ERC20ACL.sol | 47 ++++ x/evm/contracts/erc20_factory/ERC20Factory.go | 2 +- .../contracts/erc20_factory/ERC20Factory.sol | 4 +- .../contracts/erc20_registry/ERC20Registry.go | 2 +- .../erc20_registry/ERC20Registry.sol | 10 +- x/evm/contracts/i_cosmos/ICosmos.go | 64 +++++- x/evm/contracts/i_cosmos/ICosmos.sol | 6 + x/evm/contracts/i_erc20/IERC20.go | 23 +- x/evm/contracts/i_erc20/IERC20.sol | 7 + x/evm/keeper/address_test.go | 2 +- x/evm/keeper/common_test.go | 1 + x/evm/keeper/context.go | 2 - x/evm/keeper/erc20.go | 8 +- x/evm/keeper/erc20_stores.go | 12 +- x/evm/keeper/erc20_test.go | 121 ++++++++++- x/evm/keeper/keeper.go | 3 + x/evm/keeper/precompiles.go | 1 + x/evm/keeper/query_server_test.go | 2 +- x/evm/precompiles/cosmos/contract.go | 77 +++++-- x/evm/precompiles/cosmos/contract_test.go | 146 +++++++++++-- x/evm/precompiles/cosmos/types.go | 38 +++- x/evm/types/expected_keeper.go | 5 + 31 files changed, 904 insertions(+), 119 deletions(-) create mode 100644 x/evm/contracts/erc20_acl/ERC20ACL.go create mode 100644 x/evm/contracts/erc20_acl/ERC20ACL.sol diff --git a/app/app.go b/app/app.go index 5aa5a5d..18c65f5 100644 --- a/app/app.go +++ b/app/app.go @@ -697,6 +697,7 @@ func NewMinitiaApp( appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), accountKeeper, + bankKeeper, communityPoolKeeper, app.MsgServiceRouter(), app.GRPCQueryRouter(), diff --git a/app/ibc-hooks/common_test.go b/app/ibc-hooks/common_test.go index 758bbe4..85a5808 100644 --- a/app/ibc-hooks/common_test.go +++ b/app/ibc-hooks/common_test.go @@ -302,6 +302,7 @@ func _createTestInput( appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), accountKeeper, + bankKeeper, communityPoolKeeper, msgRouter, queryRouter, diff --git a/x/bank/keeper/common_test.go b/x/bank/keeper/common_test.go index aa19db5..99e3d9c 100644 --- a/x/bank/keeper/common_test.go +++ b/x/bank/keeper/common_test.go @@ -294,6 +294,7 @@ func _createTestInput( appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), accountKeeper, + bankKeeper, communityPoolKeeper, msgRouter, queryRouter, diff --git a/x/evm/contracts/counter/Counter.go b/x/evm/contracts/counter/Counter.go index f8e6fee..f2e6a41 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\":[{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"ibc_ack\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"callback_id\",\"type\":\"uint64\"}],\"name\":\"ibc_timeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"increase\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"path\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"req\",\"type\":\"string\"}],\"name\":\"query_cosmos\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"result\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561000f575f80fd5b506107cb8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610055575f3560e01c806306661abd146100595780630d4f1f9d1461007757806331a503f014610093578063cad23554146100af578063e8927fbc146100df575b5f80fd5b6100616100e9565b60405161006e9190610259565b60405180910390f35b610091600480360381019061008c91906102f5565b6100ee565b005b6100ad60048036038101906100a89190610333565b610135565b005b6100c960048036038101906100c4919061049a565b610159565b6040516100d6919061058a565b60405180910390f35b6100e76101e2565b005b5f5481565b801561011a578167ffffffffffffffff165f8082825461010e91906105d7565b92505081905550610131565b5f8081548092919061012b9061060a565b91905055505b5050565b8067ffffffffffffffff165f8082825461014f91906105d7565b9250508190555050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b8152600401610197929190610651565b5f604051808303815f875af11580156101b2573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906101da91906106f4565b905092915050565b5f808154809291906101f39061060a565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f54610227919061073b565b5f5460405161023792919061076e565b60405180910390a1565b5f819050919050565b61025381610241565b82525050565b5f60208201905061026c5f83018461024a565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b61029f81610283565b81146102a9575f80fd5b50565b5f813590506102ba81610296565b92915050565b5f8115159050919050565b6102d4816102c0565b81146102de575f80fd5b50565b5f813590506102ef816102cb565b92915050565b5f806040838503121561030b5761030a61027b565b5b5f610318858286016102ac565b9250506020610329858286016102e1565b9150509250929050565b5f602082840312156103485761034761027b565b5b5f610355848285016102ac565b91505092915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103ac82610366565b810181811067ffffffffffffffff821117156103cb576103ca610376565b5b80604052505050565b5f6103dd610272565b90506103e982826103a3565b919050565b5f67ffffffffffffffff82111561040857610407610376565b5b61041182610366565b9050602081019050919050565b828183375f83830152505050565b5f61043e610439846103ee565b6103d4565b90508281526020810184848401111561045a57610459610362565b5b61046584828561041e565b509392505050565b5f82601f8301126104815761048061035e565b5b813561049184826020860161042c565b91505092915050565b5f80604083850312156104b0576104af61027b565b5b5f83013567ffffffffffffffff8111156104cd576104cc61027f565b5b6104d98582860161046d565b925050602083013567ffffffffffffffff8111156104fa576104f961027f565b5b6105068582860161046d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561054757808201518184015260208101905061052c565b5f8484015250505050565b5f61055c82610510565b610566818561051a565b935061057681856020860161052a565b61057f81610366565b840191505092915050565b5f6020820190508181035f8301526105a28184610552565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6105e182610241565b91506105ec83610241565b9250828201905080821115610604576106036105aa565b5b92915050565b5f61061482610241565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610646576106456105aa565b5b600182019050919050565b5f6040820190508181035f8301526106698185610552565b9050818103602083015261067d8184610552565b90509392505050565b5f610698610693846103ee565b6103d4565b9050828152602081018484840111156106b4576106b3610362565b5b6106bf84828561052a565b509392505050565b5f82601f8301126106db576106da61035e565b5b81516106eb848260208601610686565b91505092915050565b5f602082840312156107095761070861027b565b5b5f82015167ffffffffffffffff8111156107265761072561027f565b5b610732848285016106c7565b91505092915050565b5f61074582610241565b915061075083610241565b9250828203905081811115610768576107676105aa565b5b92915050565b5f6040820190506107815f83018561024a565b61078e602083018461024a565b939250505056fea2646970667358221220ab434f24f747faa9977ce70064417eedf27920874d368a34f49515b3a13e60ef64736f6c63430008180033", + Bin: "0x608060405234801561000f575f80fd5b506107cb8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610055575f3560e01c806306661abd146100595780630d4f1f9d1461007757806331a503f014610093578063cad23554146100af578063e8927fbc146100df575b5f80fd5b6100616100e9565b60405161006e9190610259565b60405180910390f35b610091600480360381019061008c91906102f5565b6100ee565b005b6100ad60048036038101906100a89190610333565b610135565b005b6100c960048036038101906100c4919061049a565b610159565b6040516100d6919061058a565b60405180910390f35b6100e76101e2565b005b5f5481565b801561011a578167ffffffffffffffff165f8082825461010e91906105d7565b92505081905550610131565b5f8081548092919061012b9061060a565b91905055505b5050565b8067ffffffffffffffff165f8082825461014f91906105d7565b9250508190555050565b606060f173ffffffffffffffffffffffffffffffffffffffff1663cad2355484846040518363ffffffff1660e01b8152600401610197929190610651565b5f604051808303815f875af11580156101b2573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906101da91906106f4565b905092915050565b5f808154809291906101f39061060a565b91905055507f61996fe196f72cb598c483e896a1221263a28bb630480aa89495f737d4a8e3df60015f54610227919061073b565b5f5460405161023792919061076e565b60405180910390a1565b5f819050919050565b61025381610241565b82525050565b5f60208201905061026c5f83018461024a565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f67ffffffffffffffff82169050919050565b61029f81610283565b81146102a9575f80fd5b50565b5f813590506102ba81610296565b92915050565b5f8115159050919050565b6102d4816102c0565b81146102de575f80fd5b50565b5f813590506102ef816102cb565b92915050565b5f806040838503121561030b5761030a61027b565b5b5f610318858286016102ac565b9250506020610329858286016102e1565b9150509250929050565b5f602082840312156103485761034761027b565b5b5f610355848285016102ac565b91505092915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103ac82610366565b810181811067ffffffffffffffff821117156103cb576103ca610376565b5b80604052505050565b5f6103dd610272565b90506103e982826103a3565b919050565b5f67ffffffffffffffff82111561040857610407610376565b5b61041182610366565b9050602081019050919050565b828183375f83830152505050565b5f61043e610439846103ee565b6103d4565b90508281526020810184848401111561045a57610459610362565b5b61046584828561041e565b509392505050565b5f82601f8301126104815761048061035e565b5b813561049184826020860161042c565b91505092915050565b5f80604083850312156104b0576104af61027b565b5b5f83013567ffffffffffffffff8111156104cd576104cc61027f565b5b6104d98582860161046d565b925050602083013567ffffffffffffffff8111156104fa576104f961027f565b5b6105068582860161046d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561054757808201518184015260208101905061052c565b5f8484015250505050565b5f61055c82610510565b610566818561051a565b935061057681856020860161052a565b61057f81610366565b840191505092915050565b5f6020820190508181035f8301526105a28184610552565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6105e182610241565b91506105ec83610241565b9250828201905080821115610604576106036105aa565b5b92915050565b5f61061482610241565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610646576106456105aa565b5b600182019050919050565b5f6040820190508181035f8301526106698185610552565b9050818103602083015261067d8184610552565b90509392505050565b5f610698610693846103ee565b6103d4565b9050828152602081018484840111156106b4576106b3610362565b5b6106bf84828561052a565b509392505050565b5f82601f8301126106db576106da61035e565b5b81516106eb848260208601610686565b91505092915050565b5f602082840312156107095761070861027b565b5b5f82015167ffffffffffffffff8111156107265761072561027f565b5b610732848285016106c7565b91505092915050565b5f61074582610241565b915061075083610241565b9250828203905081811115610768576107676105aa565b5b92915050565b5f6040820190506107815f83018561024a565b61078e602083018461024a565b939250505056fea2646970667358221220442198bd46697a1b5e99d1aae94374128afbcb8f42aace4d40d27c88f31af94164736f6c63430008180033", } // CounterABI is the input ABI used to generate the binding from. diff --git a/x/evm/contracts/custom_erc20/CustomERC20.go b/x/evm/contracts/custom_erc20/CustomERC20.go index 8952eb2..989fae7 100644 --- a/x/evm/contracts/custom_erc20/CustomERC20.go +++ b/x/evm/contracts/custom_erc20/CustomERC20.go @@ -31,8 +31,8 @@ var ( // CustomErc20MetaData contains all meta data concerning the CustomErc20 contract. var CustomErc20MetaData = &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: "0x608060405234801562000010575f80fd5b5060405162001a0138038062001a018339818101604052810190620000369190620002ef565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060f273ffffffffffffffffffffffffffffffffffffffff16635e6c57596040518163ffffffff1660e01b81526004016020604051808303815f875af1158015620000c1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620000e79190620003c0565b508260039081620000f9919062000627565b5081600490816200010b919062000627565b508060055f6101000a81548160ff021916908360ff1602179055505050506200070b565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b620001908262000148565b810181811067ffffffffffffffff82111715620001b257620001b162000158565b5b80604052505050565b5f620001c66200012f565b9050620001d4828262000185565b919050565b5f67ffffffffffffffff821115620001f657620001f562000158565b5b620002018262000148565b9050602081019050919050565b5f5b838110156200022d57808201518184015260208101905062000210565b5f8484015250505050565b5f6200024e6200024884620001d9565b620001bb565b9050828152602081018484840111156200026d576200026c62000144565b5b6200027a8482856200020e565b509392505050565b5f82601f83011262000299576200029862000140565b5b8151620002ab84826020860162000238565b91505092915050565b5f60ff82169050919050565b620002cb81620002b4565b8114620002d6575f80fd5b50565b5f81519050620002e981620002c0565b92915050565b5f805f6060848603121562000309576200030862000138565b5b5f84015167ffffffffffffffff8111156200032957620003286200013c565b5b620003378682870162000282565b935050602084015167ffffffffffffffff8111156200035b576200035a6200013c565b5b620003698682870162000282565b92505060406200037c86828701620002d9565b9150509250925092565b5f8115159050919050565b6200039c8162000386565b8114620003a7575f80fd5b50565b5f81519050620003ba8162000391565b92915050565b5f60208284031215620003d857620003d762000138565b5b5f620003e784828501620003aa565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200043f57607f821691505b602082108103620004555762000454620003fa565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004b97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200047c565b620004c586836200047c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200050f620005096200050384620004dd565b620004e6565b620004dd565b9050919050565b5f819050919050565b6200052a83620004ef565b62000542620005398262000516565b84845462000488565b825550505050565b5f90565b620005586200054a565b620005658184846200051f565b505050565b5b818110156200058c57620005805f826200054e565b6001810190506200056b565b5050565b601f821115620005db57620005a5816200045b565b620005b0846200046d565b81016020851015620005c0578190505b620005d8620005cf856200046d565b8301826200056a565b50505b505050565b5f82821c905092915050565b5f620005fd5f1984600802620005e0565b1980831691505092915050565b5f620006178383620005ec565b9150826002028217905092915050565b6200063282620003f0565b67ffffffffffffffff8111156200064e576200064d62000158565b5b6200065a825462000427565b6200066782828562000590565b5f60209050601f8311600181146200069d575f841562000688578287015190505b6200069485826200060a565b86555062000703565b601f198416620006ad866200045b565b5f5b82811015620006d657848901518255600182019150602085019450602081019050620006af565b86831015620006f65784890151620006f2601f891682620005ec565b8355505b6001600288020188555050505b505050505050565b6112e880620007195f395ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac14610213578063a9059cbb1461022f578063dd62ed3e1461025f578063f2fde38b1461028f576100cd565b806370a08231146101a75780638da5cb5b146101d757806395d89b41146101f5576100cd565b806306fdde03146100d1578063095ea7b3146100ef57806318160ddd1461011f57806323b872dd1461013d578063313ce5671461016d57806340c10f191461018b575b5f80fd5b6100d96102ab565b6040516100e69190610f0e565b60405180910390f35b61010960048036038101906101049190610fbf565b610337565b6040516101169190611017565b60405180910390f35b610127610424565b604051610134919061103f565b60405180910390f35b61015760048036038101906101529190611058565b61042a565b6040516101649190611017565b60405180910390f35b6101756106ca565b60405161018291906110c3565b60405180910390f35b6101a560048036038101906101a09190610fbf565b6106dc565b005b6101c160048036038101906101bc91906110dc565b610740565b6040516101ce919061103f565b60405180910390f35b6101df610755565b6040516101ec9190611116565b60405180910390f35b6101fd610778565b60405161020a9190610f0e565b60405180910390f35b61022d60048036038101906102289190610fbf565b610804565b005b61024960048036038101906102449190610fbf565b610868565b6040516102569190611017565b60405180910390f35b6102796004803603810190610274919061112f565b610a79565b604051610286919061103f565b60405180910390f35b6102a960048036038101906102a491906110dc565b610a99565b005b600380546102b89061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546102e49061119a565b801561032f5780601f106103065761010080835404028352916020019161032f565b820191905f5260205f20905b81548152906001019060200180831161031257829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610412919061103f565b60405180910390a36001905092915050565b60065481565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016104669190611116565b602060405180830381865afa158015610481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a591906111f4565b6105255760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016104e39190611116565b6020604051808303815f875af11580156104ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052391906111f4565b505b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ac919061124c565b925050819055508260015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ff919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610652919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516106b6919061103f565b60405180910390a360019150509392505050565b60055f9054906101000a900460ff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610732575f80fd5b61073c8282610be1565b5050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107859061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546107b19061119a565b80156107fc5780601f106107d3576101008083540402835291602001916107fc565b820191905f5260205f20905b8154815290600101906020018083116107df57829003601f168201915b505050505081565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085a575f80fd5b6108648282610db0565b5050565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016108a49190611116565b602060405180830381865afa1580156108bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e391906111f4565b6109635760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016109219190611116565b6020604051808303815f875af115801561093d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096191906111f4565b505b8260015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109af919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610a02919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610a66919061103f565b60405180910390a3600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aef575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b26575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610c1c9190611116565b602060405180830381865afa158015610c37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5b91906111f4565b610cdb5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c999190611116565b6020604051808303815f875af1158015610cb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd991906111f4565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610d27919061127f565b925050819055508160065f828254610d3f919061127f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610da3919061103f565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610dfc919061124c565b925050819055508060065f828254610e14919061124c565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e78919061103f565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610ebb578082015181840152602081019050610ea0565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610ee082610e84565b610eea8185610e8e565b9350610efa818560208601610e9e565b610f0381610ec6565b840191505092915050565b5f6020820190508181035f830152610f268184610ed6565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f5b82610f32565b9050919050565b610f6b81610f51565b8114610f75575f80fd5b50565b5f81359050610f8681610f62565b92915050565b5f819050919050565b610f9e81610f8c565b8114610fa8575f80fd5b50565b5f81359050610fb981610f95565b92915050565b5f8060408385031215610fd557610fd4610f2e565b5b5f610fe285828601610f78565b9250506020610ff385828601610fab565b9150509250929050565b5f8115159050919050565b61101181610ffd565b82525050565b5f60208201905061102a5f830184611008565b92915050565b61103981610f8c565b82525050565b5f6020820190506110525f830184611030565b92915050565b5f805f6060848603121561106f5761106e610f2e565b5b5f61107c86828701610f78565b935050602061108d86828701610f78565b925050604061109e86828701610fab565b9150509250925092565b5f60ff82169050919050565b6110bd816110a8565b82525050565b5f6020820190506110d65f8301846110b4565b92915050565b5f602082840312156110f1576110f0610f2e565b5b5f6110fe84828501610f78565b91505092915050565b61111081610f51565b82525050565b5f6020820190506111295f830184611107565b92915050565b5f806040838503121561114557611144610f2e565b5b5f61115285828601610f78565b925050602061116385828601610f78565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806111b157607f821691505b6020821081036111c4576111c361116d565b5b50919050565b6111d381610ffd565b81146111dd575f80fd5b50565b5f815190506111ee816111ca565b92915050565b5f6020828403121561120957611208610f2e565b5b5f611216848285016111e0565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61125682610f8c565b915061126183610f8c565b92508282039050818111156112795761127861121f565b5b92915050565b5f61128982610f8c565b915061129483610f8c565b92508282019050808211156112ac576112ab61121f565b5b9291505056fea2646970667358221220aa0b9a634aaecddb4168bd8251192a84271901ee8fef23c1eb72ab5ed45e3ab364736f6c63430008180033", + 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\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sudoTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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: "0x608060405234801562000010575f80fd5b5060405162001d7e38038062001d7e8339818101604052810190620000369190620002ef565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060f273ffffffffffffffffffffffffffffffffffffffff16635e6c57596040518163ffffffff1660e01b81526004016020604051808303815f875af1158015620000c1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620000e79190620003c0565b508260039081620000f9919062000627565b5081600490816200010b919062000627565b508060055f6101000a81548160ff021916908360ff1602179055505050506200070b565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b620001908262000148565b810181811067ffffffffffffffff82111715620001b257620001b162000158565b5b80604052505050565b5f620001c66200012f565b9050620001d4828262000185565b919050565b5f67ffffffffffffffff821115620001f657620001f562000158565b5b620002018262000148565b9050602081019050919050565b5f5b838110156200022d57808201518184015260208101905062000210565b5f8484015250505050565b5f6200024e6200024884620001d9565b620001bb565b9050828152602081018484840111156200026d576200026c62000144565b5b6200027a8482856200020e565b509392505050565b5f82601f83011262000299576200029862000140565b5b8151620002ab84826020860162000238565b91505092915050565b5f60ff82169050919050565b620002cb81620002b4565b8114620002d6575f80fd5b50565b5f81519050620002e981620002c0565b92915050565b5f805f6060848603121562000309576200030862000138565b5b5f84015167ffffffffffffffff8111156200032957620003286200013c565b5b620003378682870162000282565b935050602084015167ffffffffffffffff8111156200035b576200035a6200013c565b5b620003698682870162000282565b92505060406200037c86828701620002d9565b9150509250925092565b5f8115159050919050565b6200039c8162000386565b8114620003a7575f80fd5b50565b5f81519050620003ba8162000391565b92915050565b5f60208284031215620003d857620003d762000138565b5b5f620003e784828501620003aa565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200043f57607f821691505b602082108103620004555762000454620003fa565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004b97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200047c565b620004c586836200047c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200050f620005096200050384620004dd565b620004e6565b620004dd565b9050919050565b5f819050919050565b6200052a83620004ef565b62000542620005398262000516565b84845462000488565b825550505050565b5f90565b620005586200054a565b620005658184846200051f565b505050565b5b818110156200058c57620005805f826200054e565b6001810190506200056b565b5050565b601f821115620005db57620005a5816200045b565b620005b0846200046d565b81016020851015620005c0578190505b620005d8620005cf856200046d565b8301826200056a565b50505b505050565b5f82821c905092915050565b5f620005fd5f1984600802620005e0565b1980831691505092915050565b5f620006178383620005ec565b9150826002028217905092915050565b6200063282620003f0565b67ffffffffffffffff8111156200064e576200064d62000158565b5b6200065a825462000427565b6200066782828562000590565b5f60209050601f8311600181146200069d575f841562000688578287015190505b6200069485826200060a565b86555062000703565b601f198416620006ad866200045b565b5f5b82811015620006d657848901518255600182019150602085019450602081019050620006af565b86831015620006f65784890151620006f2601f891682620005ec565b8355505b6001600288020188555050505b505050505050565b61166580620007195f395ff3fe608060405234801561000f575f80fd5b50600436106100e8575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac1461024a578063a9059cbb14610266578063dd62ed3e14610296578063f2fde38b146102c6576100e8565b806370a08231146101de5780638da5cb5b1461020e57806395d89b411461022c576100e8565b80631988513b116100c65780631988513b1461015857806323b872dd14610174578063313ce567146101a457806340c10f19146101c2576100e8565b806306fdde03146100ec578063095ea7b31461010a57806318160ddd1461013a575b5f80fd5b6100f46102e2565b60405161010191906110c5565b60405180910390f35b610124600480360381019061011f9190611176565b61036e565b60405161013191906111ce565b60405180910390f35b61014261045b565b60405161014f91906111f6565b60405180910390f35b610172600480360381019061016d919061120f565b610461565b005b61018e6004803603810190610189919061120f565b6104e0565b60405161019b91906111ce565b60405180910390f35b6101ac610640565b6040516101b9919061127a565b60405180910390f35b6101dc60048036038101906101d79190611176565b610652565b005b6101f860048036038101906101f39190611293565b610771565b60405161020591906111f6565b60405180910390f35b610216610786565b60405161022391906112cd565b60405180910390f35b6102346107a9565b60405161024191906110c5565b60405180910390f35b610264600480360381019061025f9190611176565b610835565b005b610280600480360381019061027b9190611176565b610954565b60405161028d91906111ce565b60405180910390f35b6102b060048036038101906102ab91906112e6565b610a25565b6040516102bd91906111f6565b60405180910390f35b6102e060048036038101906102db9190611293565b610a45565b005b600380546102ef90611351565b80601f016020809104026020016040519081016040528092919081815260200182805461031b90611351565b80156103665780601f1061033d57610100808354040283529160200191610366565b820191905f5260205f20905b81548152906001019060200180831161034957829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161044991906111f6565b60405180910390a36001905092915050565b60065481565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104c7906113cb565b60405180910390fd5b6104db838383610b8d565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b815260040161051c91906112cd565b602060405180830381865afa158015610537573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055b9190611413565b1561059b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610592906114ae565b60405180910390fd5b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461062291906114f9565b92505081905550610634858585610b8d565b60019150509392505050565b60055f9054906101000a900460ff1681565b8160f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b815260040161068d91906112cd565b602060405180830381865afa1580156106a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106cc9190611413565b1561070c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161070390611576565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610762575f80fd5b61076c8383610d98565b505050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107b690611351565b80601f01602080910402602001604051908101604052809291908181526020018280546107e290611351565b801561082d5780601f106108045761010080835404028352916020019161082d565b820191905f5260205f20905b81548152906001019060200180831161081057829003601f168201915b505050505081565b8160f173ffffffffffffffffffffffffffffffffffffffff166360dc402f826040518263ffffffff1660e01b815260040161087091906112cd565b602060405180830381865afa15801561088b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108af9190611413565b156108ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e6906115de565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610945575f80fd5b61094f8383610f67565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b815260040161099091906112cd565b602060405180830381865afa1580156109ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109cf9190611413565b15610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a06906114ae565b60405180910390fd5b610a1a338585610b8d565b600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a9b575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ad2575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610bc891906112cd565b602060405180830381865afa158015610be3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c079190611413565b610c875760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c4591906112cd565b6020604051808303815f875af1158015610c61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c859190611413565b505b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610cd391906114f9565b925050819055508160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610d2691906115fc565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d8a91906111f6565b60405180910390a350505050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610dd391906112cd565b602060405180830381865afa158015610dee573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e129190611413565b610e925760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610e5091906112cd565b6020604051808303815f875af1158015610e6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e909190611413565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610ede91906115fc565b925050819055508160065f828254610ef691906115fc565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610f5a91906111f6565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610fb391906114f9565b925050819055508060065f828254610fcb91906114f9565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161102f91906111f6565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611072578082015181840152602081019050611057565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6110978261103b565b6110a18185611045565b93506110b1818560208601611055565b6110ba8161107d565b840191505092915050565b5f6020820190508181035f8301526110dd818461108d565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611112826110e9565b9050919050565b61112281611108565b811461112c575f80fd5b50565b5f8135905061113d81611119565b92915050565b5f819050919050565b61115581611143565b811461115f575f80fd5b50565b5f813590506111708161114c565b92915050565b5f806040838503121561118c5761118b6110e5565b5b5f6111998582860161112f565b92505060206111aa85828601611162565b9150509250929050565b5f8115159050919050565b6111c8816111b4565b82525050565b5f6020820190506111e15f8301846111bf565b92915050565b6111f081611143565b82525050565b5f6020820190506112095f8301846111e7565b92915050565b5f805f60608486031215611226576112256110e5565b5b5f6112338682870161112f565b93505060206112448682870161112f565b925050604061125586828701611162565b9150509250925092565b5f60ff82169050919050565b6112748161125f565b82525050565b5f60208201905061128d5f83018461126b565b92915050565b5f602082840312156112a8576112a76110e5565b5b5f6112b58482850161112f565b91505092915050565b6112c781611108565b82525050565b5f6020820190506112e05f8301846112be565b92915050565b5f80604083850312156112fc576112fb6110e5565b5b5f6113098582860161112f565b925050602061131a8582860161112f565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061136857607f821691505b60208210810361137b5761137a611324565b5b50919050565b7f45524332303a2063616c6c6572206973206e6f742074686520636861696e00005f82015250565b5f6113b5601e83611045565b91506113c082611381565b602082019050919050565b5f6020820190508181035f8301526113e2816113a9565b9050919050565b6113f2816111b4565b81146113fc575f80fd5b50565b5f8151905061140d816113e9565b92915050565b5f60208284031215611428576114276110e5565b5b5f611435848285016113ff565b91505092915050565b7f45524332303a207472616e7366657220746f20626c6f636b65642061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f611498602283611045565b91506114a38261143e565b604082019050919050565b5f6020820190508181035f8301526114c58161148c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61150382611143565b915061150e83611143565b9250828203905081811115611526576115256114cc565b5b92915050565b7f45524332303a206d696e7420746f20626c6f636b6564206164647265737300005f82015250565b5f611560601e83611045565b915061156b8261152c565b602082019050919050565b5f6020820190508181035f83015261158d81611554565b9050919050565b7f45524332303a206275726e2066726f6d206d6f64756c652061646472657373005f82015250565b5f6115c8601f83611045565b91506115d382611594565b602082019050919050565b5f6020820190508181035f8301526115f5816115bc565b9050919050565b5f61160682611143565b915061161183611143565b9250828201905080821115611629576116286114cc565b5b9291505056fea2646970667358221220ea67eebd09c10a3a7788e4f285c68dcdba2478837b31ab3dbf7186419c9f4d3064736f6c63430008180033", } // CustomErc20ABI is the input ABI used to generate the binding from. @@ -482,6 +482,27 @@ func (_CustomErc20 *CustomErc20TransactorSession) Mint(to common.Address, amount return _CustomErc20.Contract.Mint(&_CustomErc20.TransactOpts, to, amount) } +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_CustomErc20 *CustomErc20Transactor) SudoTransfer(opts *bind.TransactOpts, sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _CustomErc20.contract.Transact(opts, "sudoTransfer", sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_CustomErc20 *CustomErc20Session) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _CustomErc20.Contract.SudoTransfer(&_CustomErc20.TransactOpts, sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_CustomErc20 *CustomErc20TransactorSession) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _CustomErc20.Contract.SudoTransfer(&_CustomErc20.TransactOpts, sender, recipient, amount) +} + // Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. // // Solidity: function transfer(address recipient, uint256 amount) returns(bool) diff --git a/x/evm/contracts/custom_erc20/CustomERC20.sol b/x/evm/contracts/custom_erc20/CustomERC20.sol index 69f79e4..f3d032e 100644 --- a/x/evm/contracts/custom_erc20/CustomERC20.sol +++ b/x/evm/contracts/custom_erc20/CustomERC20.sol @@ -4,8 +4,9 @@ pragma solidity ^0.8.24; import "../i_erc20/IERC20.sol"; import "../ownable/Ownable.sol"; import "../erc20_registry/ERC20Registry.sol"; +import "../erc20_acl/ERC20ACL.sol"; -contract CustomERC20 is IERC20, Ownable, ERC20Registry { +contract CustomERC20 is IERC20, Ownable, ERC20Registry, ERC20ACL { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, @@ -20,19 +21,46 @@ contract CustomERC20 is IERC20, Ownable, ERC20Registry { uint8 public decimals; uint256 public totalSupply; - constructor(string memory _name, string memory _symbol, uint8 _decimals) register_erc20 { + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) register_erc20 { name = _name; symbol = _symbol; decimals = _decimals; } - function transfer( + function _transfer( + address sender, address recipient, uint256 amount - ) external register_erc20_store(recipient) returns (bool) { - balanceOf[msg.sender] -= amount; + ) internal register_erc20_store(recipient) { + balanceOf[sender] -= amount; balanceOf[recipient] += amount; - emit Transfer(msg.sender, recipient, amount); + emit Transfer(sender, recipient, amount); + } + + 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 transfer( + address recipient, + uint256 amount + ) external transferable(recipient) returns (bool) { + _transfer(msg.sender, recipient, amount); return true; } @@ -46,31 +74,28 @@ contract CustomERC20 is IERC20, Ownable, ERC20Registry { address sender, address recipient, uint256 amount - ) external register_erc20_store(recipient) returns (bool) { + ) external transferable(recipient) returns (bool) { allowance[sender][msg.sender] -= amount; - balanceOf[sender] -= amount; - balanceOf[recipient] += amount; - emit Transfer(sender, recipient, amount); + _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{ + function mint(address to, uint256 amount) external mintable(to) onlyOwner { _mint(to, amount); } - function burn(address from, uint256 amount) external onlyOwner { + function burn( + address from, + uint256 amount + ) external burnable(from) onlyOwner { _burn(from, amount); } + + function sudoTransfer( + address sender, + address recipient, + uint256 amount + ) external onlyChain { + _transfer(sender, recipient, amount); + } } diff --git a/x/evm/contracts/erc20/ERC20.go b/x/evm/contracts/erc20/ERC20.go index 06056d5..448c40f 100644 --- a/x/evm/contracts/erc20/ERC20.go +++ b/x/evm/contracts/erc20/ERC20.go @@ -31,8 +31,8 @@ var ( // 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: "0x608060405234801562000010575f80fd5b50604051620019243803806200192483398181016040528101906200003691906200027c565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600390816200008691906200054a565b5081600490816200009891906200054a565b508060055f6101000a81548160ff021916908360ff1602179055505050506200062e565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200011d82620000d5565b810181811067ffffffffffffffff821117156200013f576200013e620000e5565b5b80604052505050565b5f62000153620000bc565b905062000161828262000112565b919050565b5f67ffffffffffffffff821115620001835762000182620000e5565b5b6200018e82620000d5565b9050602081019050919050565b5f5b83811015620001ba5780820151818401526020810190506200019d565b5f8484015250505050565b5f620001db620001d58462000166565b62000148565b905082815260208101848484011115620001fa57620001f9620000d1565b5b620002078482856200019b565b509392505050565b5f82601f830112620002265762000225620000cd565b5b815162000238848260208601620001c5565b91505092915050565b5f60ff82169050919050565b620002588162000241565b811462000263575f80fd5b50565b5f8151905062000276816200024d565b92915050565b5f805f60608486031215620002965762000295620000c5565b5b5f84015167ffffffffffffffff811115620002b657620002b5620000c9565b5b620002c4868287016200020f565b935050602084015167ffffffffffffffff811115620002e857620002e7620000c9565b5b620002f6868287016200020f565b9250506040620003098682870162000266565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200036257607f821691505b6020821081036200037857620003776200031d565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003dc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200039f565b620003e886836200039f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004326200042c620004268462000400565b62000409565b62000400565b9050919050565b5f819050919050565b6200044d8362000412565b620004656200045c8262000439565b848454620003ab565b825550505050565b5f90565b6200047b6200046d565b6200048881848462000442565b505050565b5b81811015620004af57620004a35f8262000471565b6001810190506200048e565b5050565b601f821115620004fe57620004c8816200037e565b620004d38462000390565b81016020851015620004e3578190505b620004fb620004f28562000390565b8301826200048d565b50505b505050565b5f82821c905092915050565b5f620005205f198460080262000503565b1980831691505092915050565b5f6200053a83836200050f565b9150826002028217905092915050565b620005558262000313565b67ffffffffffffffff811115620005715762000570620000e5565b5b6200057d82546200034a565b6200058a828285620004b3565b5f60209050601f831160018114620005c0575f8415620005ab578287015190505b620005b785826200052d565b86555062000626565b601f198416620005d0866200037e565b5f5b82811015620005f957848901518255600182019150602085019450602081019050620005d2565b8683101562000619578489015162000615601f8916826200050f565b8355505b6001600288020188555050505b505050505050565b6112e8806200063c5f395ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac14610213578063a9059cbb1461022f578063dd62ed3e1461025f578063f2fde38b1461028f576100cd565b806370a08231146101a75780638da5cb5b146101d757806395d89b41146101f5576100cd565b806306fdde03146100d1578063095ea7b3146100ef57806318160ddd1461011f57806323b872dd1461013d578063313ce5671461016d57806340c10f191461018b575b5f80fd5b6100d96102ab565b6040516100e69190610f0e565b60405180910390f35b61010960048036038101906101049190610fbf565b610337565b6040516101169190611017565b60405180910390f35b610127610424565b604051610134919061103f565b60405180910390f35b61015760048036038101906101529190611058565b61042a565b6040516101649190611017565b60405180910390f35b6101756106ca565b60405161018291906110c3565b60405180910390f35b6101a560048036038101906101a09190610fbf565b6106dc565b005b6101c160048036038101906101bc91906110dc565b610740565b6040516101ce919061103f565b60405180910390f35b6101df610755565b6040516101ec9190611116565b60405180910390f35b6101fd610778565b60405161020a9190610f0e565b60405180910390f35b61022d60048036038101906102289190610fbf565b610804565b005b61024960048036038101906102449190610fbf565b610868565b6040516102569190611017565b60405180910390f35b6102796004803603810190610274919061112f565b610a79565b604051610286919061103f565b60405180910390f35b6102a960048036038101906102a491906110dc565b610a99565b005b600380546102b89061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546102e49061119a565b801561032f5780601f106103065761010080835404028352916020019161032f565b820191905f5260205f20905b81548152906001019060200180831161031257829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610412919061103f565b60405180910390a36001905092915050565b60065481565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016104669190611116565b602060405180830381865afa158015610481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a591906111f4565b6105255760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016104e39190611116565b6020604051808303815f875af11580156104ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052391906111f4565b505b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ac919061124c565b925050819055508260015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ff919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610652919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516106b6919061103f565b60405180910390a360019150509392505050565b60055f9054906101000a900460ff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610732575f80fd5b61073c8282610be1565b5050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107859061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546107b19061119a565b80156107fc5780601f106107d3576101008083540402835291602001916107fc565b820191905f5260205f20905b8154815290600101906020018083116107df57829003601f168201915b505050505081565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085a575f80fd5b6108648282610db0565b5050565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016108a49190611116565b602060405180830381865afa1580156108bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e391906111f4565b6109635760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016109219190611116565b6020604051808303815f875af115801561093d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096191906111f4565b505b8260015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109af919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610a02919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610a66919061103f565b60405180910390a3600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aef575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b26575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610c1c9190611116565b602060405180830381865afa158015610c37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5b91906111f4565b610cdb5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c999190611116565b6020604051808303815f875af1158015610cb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd991906111f4565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610d27919061127f565b925050819055508160065f828254610d3f919061127f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610da3919061103f565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610dfc919061124c565b925050819055508060065f828254610e14919061124c565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e78919061103f565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610ebb578082015181840152602081019050610ea0565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610ee082610e84565b610eea8185610e8e565b9350610efa818560208601610e9e565b610f0381610ec6565b840191505092915050565b5f6020820190508181035f830152610f268184610ed6565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f5b82610f32565b9050919050565b610f6b81610f51565b8114610f75575f80fd5b50565b5f81359050610f8681610f62565b92915050565b5f819050919050565b610f9e81610f8c565b8114610fa8575f80fd5b50565b5f81359050610fb981610f95565b92915050565b5f8060408385031215610fd557610fd4610f2e565b5b5f610fe285828601610f78565b9250506020610ff385828601610fab565b9150509250929050565b5f8115159050919050565b61101181610ffd565b82525050565b5f60208201905061102a5f830184611008565b92915050565b61103981610f8c565b82525050565b5f6020820190506110525f830184611030565b92915050565b5f805f6060848603121561106f5761106e610f2e565b5b5f61107c86828701610f78565b935050602061108d86828701610f78565b925050604061109e86828701610fab565b9150509250925092565b5f60ff82169050919050565b6110bd816110a8565b82525050565b5f6020820190506110d65f8301846110b4565b92915050565b5f602082840312156110f1576110f0610f2e565b5b5f6110fe84828501610f78565b91505092915050565b61111081610f51565b82525050565b5f6020820190506111295f830184611107565b92915050565b5f806040838503121561114557611144610f2e565b5b5f61115285828601610f78565b925050602061116385828601610f78565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806111b157607f821691505b6020821081036111c4576111c361116d565b5b50919050565b6111d381610ffd565b81146111dd575f80fd5b50565b5f815190506111ee816111ca565b92915050565b5f6020828403121561120957611208610f2e565b5b5f611216848285016111e0565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61125682610f8c565b915061126183610f8c565b92508282039050818111156112795761127861121f565b5b92915050565b5f61128982610f8c565b915061129483610f8c565b92508282019050808211156112ac576112ab61121f565b5b9291505056fea26469706673582212200d99d18248e83d210e18f23ff87e4eb89c4a2794c313c7d44e6df4c88a1bb1f964736f6c63430008180033", + 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\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sudoBurn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sudoMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sudoTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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: "0x608060405234801562000010575f80fd5b5060405162001de938038062001de983398181016040528101906200003691906200027c565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600390816200008691906200054a565b5081600490816200009891906200054a565b508060055f6101000a81548160ff021916908360ff1602179055505050506200062e565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200011d82620000d5565b810181811067ffffffffffffffff821117156200013f576200013e620000e5565b5b80604052505050565b5f62000153620000bc565b905062000161828262000112565b919050565b5f67ffffffffffffffff821115620001835762000182620000e5565b5b6200018e82620000d5565b9050602081019050919050565b5f5b83811015620001ba5780820151818401526020810190506200019d565b5f8484015250505050565b5f620001db620001d58462000166565b62000148565b905082815260208101848484011115620001fa57620001f9620000d1565b5b620002078482856200019b565b509392505050565b5f82601f830112620002265762000225620000cd565b5b815162000238848260208601620001c5565b91505092915050565b5f60ff82169050919050565b620002588162000241565b811462000263575f80fd5b50565b5f8151905062000276816200024d565b92915050565b5f805f60608486031215620002965762000295620000c5565b5b5f84015167ffffffffffffffff811115620002b657620002b5620000c9565b5b620002c4868287016200020f565b935050602084015167ffffffffffffffff811115620002e857620002e7620000c9565b5b620002f6868287016200020f565b9250506040620003098682870162000266565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200036257607f821691505b6020821081036200037857620003776200031d565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003dc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200039f565b620003e886836200039f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004326200042c620004268462000400565b62000409565b62000400565b9050919050565b5f819050919050565b6200044d8362000412565b620004656200045c8262000439565b848454620003ab565b825550505050565b5f90565b6200047b6200046d565b6200048881848462000442565b505050565b5b81811015620004af57620004a35f8262000471565b6001810190506200048e565b5050565b601f821115620004fe57620004c8816200037e565b620004d38462000390565b81016020851015620004e3578190505b620004fb620004f28562000390565b8301826200048d565b50505b505050565b5f82821c905092915050565b5f620005205f198460080262000503565b1980831691505092915050565b5f6200053a83836200050f565b9150826002028217905092915050565b620005558262000313565b67ffffffffffffffff811115620005715762000570620000e5565b5b6200057d82546200034a565b6200058a828285620004b3565b5f60209050601f831160018114620005c0575f8415620005ab578287015190505b620005b785826200052d565b86555062000626565b601f198416620005d0866200037e565b5f5b82811015620005f957848901518255600182019150602085019450602081019050620005d2565b8683101562000619578489015162000615601f8916826200050f565b8355505b6001600288020188555050505b505050505050565b6117ad806200063c5f395ff3fe608060405234801561000f575f80fd5b50600436106100fe575f3560e01c806370a0823111610095578063a9059cbb11610064578063a9059cbb14610298578063dd62ed3e146102c8578063f2fde38b146102f8578063fe1195ec14610314576100fe565b806370a08231146102105780638da5cb5b1461024057806395d89b411461025e5780639dc29fac1461027c576100fe565b806323b872dd116100d157806323b872dd1461018a5780632d688ca8146101ba578063313ce567146101d657806340c10f19146101f4576100fe565b806306fdde0314610102578063095ea7b31461012057806318160ddd146101505780631988513b1461016e575b5f80fd5b61010a610330565b604051610117919061120d565b60405180910390f35b61013a600480360381019061013591906112be565b6103bc565b6040516101479190611316565b60405180910390f35b6101586104a9565b604051610165919061133e565b60405180910390f35b61018860048036038101906101839190611357565b6104af565b005b6101a4600480360381019061019f9190611357565b61052e565b6040516101b19190611316565b60405180910390f35b6101d460048036038101906101cf91906112be565b61068e565b005b6101de61070b565b6040516101eb91906113c2565b60405180910390f35b61020e600480360381019061020991906112be565b61071d565b005b61022a600480360381019061022591906113db565b61083c565b604051610237919061133e565b60405180910390f35b610248610851565b6040516102559190611415565b60405180910390f35b610266610874565b604051610273919061120d565b60405180910390f35b610296600480360381019061029191906112be565b610900565b005b6102b260048036038101906102ad91906112be565b610a1f565b6040516102bf9190611316565b60405180910390f35b6102e260048036038101906102dd919061142e565b610af0565b6040516102ef919061133e565b60405180910390f35b610312600480360381019061030d91906113db565b610b10565b005b61032e600480360381019061032991906112be565b610c58565b005b6003805461033d90611499565b80601f016020809104026020016040519081016040528092919081815260200182805461036990611499565b80156103b45780601f1061038b576101008083540402835291602001916103b4565b820191905f5260205f20905b81548152906001019060200180831161039757829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610497919061133e565b60405180910390a36001905092915050565b60065481565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590611513565b60405180910390fd5b610529838383610cd5565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b815260040161056a9190611415565b602060405180830381865afa158015610585573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a9919061155b565b156105e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e0906115f6565b60405180910390fd5b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546106709190611641565b92505081905550610682858585610cd5565b60019150509392505050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f490611513565b60405180910390fd5b6107078282610ee0565b5050565b60055f9054906101000a900460ff1681565b8160f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b81526004016107589190611415565b602060405180830381865afa158015610773573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610797919061155b565b156107d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ce906116be565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461082d575f80fd5b6108378383610ee0565b505050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6004805461088190611499565b80601f01602080910402602001604051908101604052809291908181526020018280546108ad90611499565b80156108f85780601f106108cf576101008083540402835291602001916108f8565b820191905f5260205f20905b8154815290600101906020018083116108db57829003601f168201915b505050505081565b8160f173ffffffffffffffffffffffffffffffffffffffff166360dc402f826040518263ffffffff1660e01b815260040161093b9190611415565b602060405180830381865afa158015610956573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061097a919061155b565b156109ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b190611726565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a10575f80fd5b610a1a83836110af565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b8152600401610a5b9190611415565b602060405180830381865afa158015610a76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9a919061155b565b15610ada576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad1906115f6565b60405180910390fd5b610ae5338585610cd5565b600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b66575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b9d575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cbe90611513565b60405180910390fd5b610cd182826110af565b5050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610d109190611415565b602060405180830381865afa158015610d2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4f919061155b565b610dcf5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610d8d9190611415565b6020604051808303815f875af1158015610da9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dcd919061155b565b505b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e1b9190611641565b925050819055508160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e6e9190611744565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ed2919061133e565b60405180910390a350505050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610f1b9190611415565b602060405180830381865afa158015610f36573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5a919061155b565b610fda5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610f989190611415565b6020604051808303815f875af1158015610fb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fd8919061155b565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110269190611744565b925050819055508160065f82825461103e9190611744565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516110a2919061133e565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110fb9190611641565b925050819055508060065f8282546111139190611641565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611177919061133e565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156111ba57808201518184015260208101905061119f565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6111df82611183565b6111e9818561118d565b93506111f981856020860161119d565b611202816111c5565b840191505092915050565b5f6020820190508181035f83015261122581846111d5565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61125a82611231565b9050919050565b61126a81611250565b8114611274575f80fd5b50565b5f8135905061128581611261565b92915050565b5f819050919050565b61129d8161128b565b81146112a7575f80fd5b50565b5f813590506112b881611294565b92915050565b5f80604083850312156112d4576112d361122d565b5b5f6112e185828601611277565b92505060206112f2858286016112aa565b9150509250929050565b5f8115159050919050565b611310816112fc565b82525050565b5f6020820190506113295f830184611307565b92915050565b6113388161128b565b82525050565b5f6020820190506113515f83018461132f565b92915050565b5f805f6060848603121561136e5761136d61122d565b5b5f61137b86828701611277565b935050602061138c86828701611277565b925050604061139d868287016112aa565b9150509250925092565b5f60ff82169050919050565b6113bc816113a7565b82525050565b5f6020820190506113d55f8301846113b3565b92915050565b5f602082840312156113f0576113ef61122d565b5b5f6113fd84828501611277565b91505092915050565b61140f81611250565b82525050565b5f6020820190506114285f830184611406565b92915050565b5f80604083850312156114445761144361122d565b5b5f61145185828601611277565b925050602061146285828601611277565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806114b057607f821691505b6020821081036114c3576114c261146c565b5b50919050565b7f45524332303a2063616c6c6572206973206e6f742074686520636861696e00005f82015250565b5f6114fd601e8361118d565b9150611508826114c9565b602082019050919050565b5f6020820190508181035f83015261152a816114f1565b9050919050565b61153a816112fc565b8114611544575f80fd5b50565b5f8151905061155581611531565b92915050565b5f602082840312156115705761156f61122d565b5b5f61157d84828501611547565b91505092915050565b7f45524332303a207472616e7366657220746f20626c6f636b65642061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f6115e060228361118d565b91506115eb82611586565b604082019050919050565b5f6020820190508181035f83015261160d816115d4565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61164b8261128b565b91506116568361128b565b925082820390508181111561166e5761166d611614565b5b92915050565b7f45524332303a206d696e7420746f20626c6f636b6564206164647265737300005f82015250565b5f6116a8601e8361118d565b91506116b382611674565b602082019050919050565b5f6020820190508181035f8301526116d58161169c565b9050919050565b7f45524332303a206275726e2066726f6d206d6f64756c652061646472657373005f82015250565b5f611710601f8361118d565b915061171b826116dc565b602082019050919050565b5f6020820190508181035f83015261173d81611704565b9050919050565b5f61174e8261128b565b91506117598361128b565b925082820190508082111561177157611770611614565b5b9291505056fea26469706673582212200b811e3223eb1f009f52b242d4bf732a6b5ece5baaf4b10f1dcd217cee86754a64736f6c63430008180033", } // Erc20ABI is the input ABI used to generate the binding from. @@ -482,6 +482,69 @@ func (_Erc20 *Erc20TransactorSession) Mint(to common.Address, amount *big.Int) ( return _Erc20.Contract.Mint(&_Erc20.TransactOpts, to, amount) } +// SudoBurn is a paid mutator transaction binding the contract method 0xfe1195ec. +// +// Solidity: function sudoBurn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) SudoBurn(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "sudoBurn", from, amount) +} + +// SudoBurn is a paid mutator transaction binding the contract method 0xfe1195ec. +// +// Solidity: function sudoBurn(address from, uint256 amount) returns() +func (_Erc20 *Erc20Session) SudoBurn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoBurn(&_Erc20.TransactOpts, from, amount) +} + +// SudoBurn is a paid mutator transaction binding the contract method 0xfe1195ec. +// +// Solidity: function sudoBurn(address from, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) SudoBurn(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoBurn(&_Erc20.TransactOpts, from, amount) +} + +// SudoMint is a paid mutator transaction binding the contract method 0x2d688ca8. +// +// Solidity: function sudoMint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) SudoMint(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "sudoMint", to, amount) +} + +// SudoMint is a paid mutator transaction binding the contract method 0x2d688ca8. +// +// Solidity: function sudoMint(address to, uint256 amount) returns() +func (_Erc20 *Erc20Session) SudoMint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoMint(&_Erc20.TransactOpts, to, amount) +} + +// SudoMint is a paid mutator transaction binding the contract method 0x2d688ca8. +// +// Solidity: function sudoMint(address to, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) SudoMint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoMint(&_Erc20.TransactOpts, to, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_Erc20 *Erc20Transactor) SudoTransfer(opts *bind.TransactOpts, sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.contract.Transact(opts, "sudoTransfer", sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_Erc20 *Erc20Session) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoTransfer(&_Erc20.TransactOpts, sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_Erc20 *Erc20TransactorSession) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Erc20.Contract.SudoTransfer(&_Erc20.TransactOpts, sender, recipient, amount) +} + // Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. // // Solidity: function transfer(address recipient, uint256 amount) returns(bool) diff --git a/x/evm/contracts/erc20/ERC20.sol b/x/evm/contracts/erc20/ERC20.sol index 7e6037a..b73e866 100644 --- a/x/evm/contracts/erc20/ERC20.sol +++ b/x/evm/contracts/erc20/ERC20.sol @@ -4,8 +4,9 @@ pragma solidity ^0.8.24; import "../i_erc20/IERC20.sol"; import "../ownable/Ownable.sol"; import "../erc20_registry/ERC20Registry.sol"; +import "../erc20_acl/ERC20ACL.sol"; -contract ERC20 is IERC20, Ownable, ERC20Registry { +contract ERC20 is IERC20, Ownable, ERC20Registry, ERC20ACL { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, @@ -27,13 +28,36 @@ contract ERC20 is IERC20, Ownable, ERC20Registry { decimals = _decimals; } - function transfer( + function _transfer( + address sender, address recipient, uint256 amount - ) external register_erc20_store(recipient) returns (bool) { - balanceOf[msg.sender] -= amount; + ) internal register_erc20_store(recipient) { + balanceOf[sender] -= amount; balanceOf[recipient] += amount; - emit Transfer(msg.sender, recipient, amount); + emit Transfer(sender, recipient, amount); + } + + 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 transfer( + address recipient, + uint256 amount + ) external transferable(recipient) returns (bool) { + _transfer(msg.sender, recipient, amount); return true; } @@ -47,31 +71,36 @@ contract ERC20 is IERC20, Ownable, ERC20Registry { address sender, address recipient, uint256 amount - ) external register_erc20_store(recipient) returns (bool) { + ) external transferable(recipient) returns (bool) { allowance[sender][msg.sender] -= amount; - balanceOf[sender] -= amount; - balanceOf[recipient] += amount; - emit Transfer(sender, recipient, amount); + _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 mint(address to, uint256 amount) external mintable(to) onlyOwner { + _mint(to, amount); } - function _burn(address from, uint256 amount) internal { - balanceOf[from] -= amount; - totalSupply -= amount; - emit Transfer(from, address(0), amount); + function burn( + address from, + uint256 amount + ) external burnable(from) onlyOwner { + _burn(from, amount); + } + + function sudoTransfer( + address sender, + address recipient, + uint256 amount + ) external onlyChain { + _transfer(sender, recipient, amount); } - function mint(address to, uint256 amount) external onlyOwner{ + function sudoMint(address to, uint256 amount) external onlyChain { _mint(to, amount); } - function burn(address from, uint256 amount) external onlyOwner { + function sudoBurn(address from, uint256 amount) external onlyChain { _burn(from, amount); } } diff --git a/x/evm/contracts/erc20_acl/ERC20ACL.go b/x/evm/contracts/erc20_acl/ERC20ACL.go new file mode 100644 index 0000000..7880a08 --- /dev/null +++ b/x/evm/contracts/erc20_acl/ERC20ACL.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_acl + +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 +) + +// Erc20AclMetaData contains all meta data concerning the Erc20Acl contract. +var Erc20AclMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea264697066735822122097f44a6309abb239e19ee1005989fb200d740afc2223e4d6c0fb82a45f806dec64736f6c63430008180033", +} + +// Erc20AclABI is the input ABI used to generate the binding from. +// Deprecated: Use Erc20AclMetaData.ABI instead. +var Erc20AclABI = Erc20AclMetaData.ABI + +// Erc20AclBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use Erc20AclMetaData.Bin instead. +var Erc20AclBin = Erc20AclMetaData.Bin + +// DeployErc20Acl deploys a new Ethereum contract, binding an instance of Erc20Acl to it. +func DeployErc20Acl(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Erc20Acl, error) { + parsed, err := Erc20AclMetaData.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(Erc20AclBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Erc20Acl{Erc20AclCaller: Erc20AclCaller{contract: contract}, Erc20AclTransactor: Erc20AclTransactor{contract: contract}, Erc20AclFilterer: Erc20AclFilterer{contract: contract}}, nil +} + +// Erc20Acl is an auto generated Go binding around an Ethereum contract. +type Erc20Acl struct { + Erc20AclCaller // Read-only binding to the contract + Erc20AclTransactor // Write-only binding to the contract + Erc20AclFilterer // Log filterer for contract events +} + +// Erc20AclCaller is an auto generated read-only Go binding around an Ethereum contract. +type Erc20AclCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20AclTransactor is an auto generated write-only Go binding around an Ethereum contract. +type Erc20AclTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20AclFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Erc20AclFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Erc20AclSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Erc20AclSession struct { + Contract *Erc20Acl // 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 +} + +// Erc20AclCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Erc20AclCallerSession struct { + Contract *Erc20AclCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Erc20AclTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Erc20AclTransactorSession struct { + Contract *Erc20AclTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Erc20AclRaw is an auto generated low-level Go binding around an Ethereum contract. +type Erc20AclRaw struct { + Contract *Erc20Acl // Generic contract binding to access the raw methods on +} + +// Erc20AclCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Erc20AclCallerRaw struct { + Contract *Erc20AclCaller // Generic read-only contract binding to access the raw methods on +} + +// Erc20AclTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Erc20AclTransactorRaw struct { + Contract *Erc20AclTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewErc20Acl creates a new instance of Erc20Acl, bound to a specific deployed contract. +func NewErc20Acl(address common.Address, backend bind.ContractBackend) (*Erc20Acl, error) { + contract, err := bindErc20Acl(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Erc20Acl{Erc20AclCaller: Erc20AclCaller{contract: contract}, Erc20AclTransactor: Erc20AclTransactor{contract: contract}, Erc20AclFilterer: Erc20AclFilterer{contract: contract}}, nil +} + +// NewErc20AclCaller creates a new read-only instance of Erc20Acl, bound to a specific deployed contract. +func NewErc20AclCaller(address common.Address, caller bind.ContractCaller) (*Erc20AclCaller, error) { + contract, err := bindErc20Acl(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Erc20AclCaller{contract: contract}, nil +} + +// NewErc20AclTransactor creates a new write-only instance of Erc20Acl, bound to a specific deployed contract. +func NewErc20AclTransactor(address common.Address, transactor bind.ContractTransactor) (*Erc20AclTransactor, error) { + contract, err := bindErc20Acl(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Erc20AclTransactor{contract: contract}, nil +} + +// NewErc20AclFilterer creates a new log filterer instance of Erc20Acl, bound to a specific deployed contract. +func NewErc20AclFilterer(address common.Address, filterer bind.ContractFilterer) (*Erc20AclFilterer, error) { + contract, err := bindErc20Acl(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Erc20AclFilterer{contract: contract}, nil +} + +// bindErc20Acl binds a generic wrapper to an already deployed contract. +func bindErc20Acl(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Erc20AclMetaData.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 (_Erc20Acl *Erc20AclRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Acl.Contract.Erc20AclCaller.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 (_Erc20Acl *Erc20AclRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Acl.Contract.Erc20AclTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Acl *Erc20AclRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Acl.Contract.Erc20AclTransactor.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 (_Erc20Acl *Erc20AclCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Erc20Acl.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 (_Erc20Acl *Erc20AclTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Erc20Acl.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Erc20Acl *Erc20AclTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Erc20Acl.Contract.contract.Transact(opts, method, params...) +} diff --git a/x/evm/contracts/erc20_acl/ERC20ACL.sol b/x/evm/contracts/erc20_acl/ERC20ACL.sol new file mode 100644 index 0000000..a4e48a4 --- /dev/null +++ b/x/evm/contracts/erc20_acl/ERC20ACL.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../i_cosmos/ICosmos.sol"; + +/// @dev CHAIN_ADDRESS is the address of the chain signer. +address constant CHAIN_ADDRESS = 0x0000000000000000000000000000000000000001; + +/** + * @title ERC20ACL + */ +contract ERC20ACL { + modifier onlyChain() { + require(msg.sender == CHAIN_ADDRESS, "ERC20: caller is not the chain"); + _; + } + + // check if the sender is a module address + modifier burnable(address from) { + require( + !COSMOS_CONTRACT.is_module_address(from), + "ERC20: burn from module address" + ); + + _; + } + + // check if the recipient is a blocked address + modifier mintable(address to) { + require( + !COSMOS_CONTRACT.is_blocked_address(to), + "ERC20: mint to blocked address" + ); + + _; + } + + // check if an recipient is blocked in bank module + modifier transferable(address to) { + require( + !COSMOS_CONTRACT.is_blocked_address(to), + "ERC20: transfer to blocked address" + ); + + _; + } +} diff --git a/x/evm/contracts/erc20_factory/ERC20Factory.go b/x/evm/contracts/erc20_factory/ERC20Factory.go index 28e6568..af90538 100644 --- a/x/evm/contracts/erc20_factory/ERC20Factory.go +++ b/x/evm/contracts/erc20_factory/ERC20Factory.go @@ -32,7 +32,7 @@ var ( // Erc20FactoryMetaData contains all meta data concerning the Erc20Factory contract. var Erc20FactoryMetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"erc20\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"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\":\"createERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561000f575f80fd5b50611f3c8061001d5f395ff3fe608060405234801562000010575f80fd5b50600436106200002c575f3560e01c806306ef1a861462000030575b5f80fd5b6200004e6004803603810190620000489190620003a5565b62000066565b6040516200005d91906200047f565b60405180910390f35b5f808484846040516200007990620001f3565b62000087939291906200052f565b604051809103905ff080158015620000a1573d5f803e3d5ffd5b50905060f273ffffffffffffffffffffffffffffffffffffffff1663d126274a826040518263ffffffff1660e01b8152600401620000e091906200047f565b6020604051808303815f875af1158015620000fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001239190620005b2565b508073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b336040518263ffffffff1660e01b81526004016200015f91906200047f565b5f604051808303815f87803b15801562000177575f80fd5b505af11580156200018a573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d160405160405180910390a3809150509392505050565b61192480620005e383390190565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b62000262826200021a565b810181811067ffffffffffffffff821117156200028457620002836200022a565b5b80604052505050565b5f6200029862000201565b9050620002a6828262000257565b919050565b5f67ffffffffffffffff821115620002c857620002c76200022a565b5b620002d3826200021a565b9050602081019050919050565b828183375f83830152505050565b5f62000304620002fe84620002ab565b6200028d565b90508281526020810184848401111562000323576200032262000216565b5b62000330848285620002e0565b509392505050565b5f82601f8301126200034f576200034e62000212565b5b813562000361848260208601620002ee565b91505092915050565b5f60ff82169050919050565b62000381816200036a565b81146200038c575f80fd5b50565b5f813590506200039f8162000376565b92915050565b5f805f60608486031215620003bf57620003be6200020a565b5b5f84013567ffffffffffffffff811115620003df57620003de6200020e565b5b620003ed8682870162000338565b935050602084013567ffffffffffffffff8111156200041157620004106200020e565b5b6200041f8682870162000338565b925050604062000432868287016200038f565b9150509250925092565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000467826200043c565b9050919050565b62000479816200045b565b82525050565b5f602082019050620004945f8301846200046e565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015620004d3578082015181840152602081019050620004b6565b5f8484015250505050565b5f620004ea826200049a565b620004f68185620004a4565b935062000508818560208601620004b4565b62000513816200021a565b840191505092915050565b62000529816200036a565b82525050565b5f6060820190508181035f830152620005498186620004de565b905081810360208301526200055f8185620004de565b90506200057060408301846200051e565b949350505050565b5f8115159050919050565b6200058e8162000578565b811462000599575f80fd5b50565b5f81519050620005ac8162000583565b92915050565b5f60208284031215620005ca57620005c96200020a565b5b5f620005d9848285016200059c565b9150509291505056fe608060405234801562000010575f80fd5b50604051620019243803806200192483398181016040528101906200003691906200027c565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600390816200008691906200054a565b5081600490816200009891906200054a565b508060055f6101000a81548160ff021916908360ff1602179055505050506200062e565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200011d82620000d5565b810181811067ffffffffffffffff821117156200013f576200013e620000e5565b5b80604052505050565b5f62000153620000bc565b905062000161828262000112565b919050565b5f67ffffffffffffffff821115620001835762000182620000e5565b5b6200018e82620000d5565b9050602081019050919050565b5f5b83811015620001ba5780820151818401526020810190506200019d565b5f8484015250505050565b5f620001db620001d58462000166565b62000148565b905082815260208101848484011115620001fa57620001f9620000d1565b5b620002078482856200019b565b509392505050565b5f82601f830112620002265762000225620000cd565b5b815162000238848260208601620001c5565b91505092915050565b5f60ff82169050919050565b620002588162000241565b811462000263575f80fd5b50565b5f8151905062000276816200024d565b92915050565b5f805f60608486031215620002965762000295620000c5565b5b5f84015167ffffffffffffffff811115620002b657620002b5620000c9565b5b620002c4868287016200020f565b935050602084015167ffffffffffffffff811115620002e857620002e7620000c9565b5b620002f6868287016200020f565b9250506040620003098682870162000266565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200036257607f821691505b6020821081036200037857620003776200031d565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003dc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200039f565b620003e886836200039f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004326200042c620004268462000400565b62000409565b62000400565b9050919050565b5f819050919050565b6200044d8362000412565b620004656200045c8262000439565b848454620003ab565b825550505050565b5f90565b6200047b6200046d565b6200048881848462000442565b505050565b5b81811015620004af57620004a35f8262000471565b6001810190506200048e565b5050565b601f821115620004fe57620004c8816200037e565b620004d38462000390565b81016020851015620004e3578190505b620004fb620004f28562000390565b8301826200048d565b50505b505050565b5f82821c905092915050565b5f620005205f198460080262000503565b1980831691505092915050565b5f6200053a83836200050f565b9150826002028217905092915050565b620005558262000313565b67ffffffffffffffff811115620005715762000570620000e5565b5b6200057d82546200034a565b6200058a828285620004b3565b5f60209050601f831160018114620005c0575f8415620005ab578287015190505b620005b785826200052d565b86555062000626565b601f198416620005d0866200037e565b5f5b82811015620005f957848901518255600182019150602085019450602081019050620005d2565b8683101562000619578489015162000615601f8916826200050f565b8355505b6001600288020188555050505b505050505050565b6112e8806200063c5f395ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c806370a082311161008a5780639dc29fac116100645780639dc29fac14610213578063a9059cbb1461022f578063dd62ed3e1461025f578063f2fde38b1461028f576100cd565b806370a08231146101a75780638da5cb5b146101d757806395d89b41146101f5576100cd565b806306fdde03146100d1578063095ea7b3146100ef57806318160ddd1461011f57806323b872dd1461013d578063313ce5671461016d57806340c10f191461018b575b5f80fd5b6100d96102ab565b6040516100e69190610f0e565b60405180910390f35b61010960048036038101906101049190610fbf565b610337565b6040516101169190611017565b60405180910390f35b610127610424565b604051610134919061103f565b60405180910390f35b61015760048036038101906101529190611058565b61042a565b6040516101649190611017565b60405180910390f35b6101756106ca565b60405161018291906110c3565b60405180910390f35b6101a560048036038101906101a09190610fbf565b6106dc565b005b6101c160048036038101906101bc91906110dc565b610740565b6040516101ce919061103f565b60405180910390f35b6101df610755565b6040516101ec9190611116565b60405180910390f35b6101fd610778565b60405161020a9190610f0e565b60405180910390f35b61022d60048036038101906102289190610fbf565b610804565b005b61024960048036038101906102449190610fbf565b610868565b6040516102569190611017565b60405180910390f35b6102796004803603810190610274919061112f565b610a79565b604051610286919061103f565b60405180910390f35b6102a960048036038101906102a491906110dc565b610a99565b005b600380546102b89061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546102e49061119a565b801561032f5780601f106103065761010080835404028352916020019161032f565b820191905f5260205f20905b81548152906001019060200180831161031257829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610412919061103f565b60405180910390a36001905092915050565b60065481565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016104669190611116565b602060405180830381865afa158015610481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a591906111f4565b6105255760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016104e39190611116565b6020604051808303815f875af11580156104ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052391906111f4565b505b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ac919061124c565b925050819055508260015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ff919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610652919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040516106b6919061103f565b60405180910390a360019150509392505050565b60055f9054906101000a900460ff1681565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610732575f80fd5b61073c8282610be1565b5050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546107859061119a565b80601f01602080910402602001604051908101604052809291908181526020018280546107b19061119a565b80156107fc5780601f106107d3576101008083540402835291602001916107fc565b820191905f5260205f20905b8154815290600101906020018083116107df57829003601f168201915b505050505081565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085a575f80fd5b6108648282610db0565b5050565b5f8260f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b81526004016108a49190611116565b602060405180830381865afa1580156108bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e391906111f4565b6109635760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b81526004016109219190611116565b6020604051808303815f875af115801561093d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096191906111f4565b505b8260015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546109af919061124c565b925050819055508260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610a02919061127f565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610a66919061103f565b60405180910390a3600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aef575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b26575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610c1c9190611116565b602060405180830381865afa158015610c37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5b91906111f4565b610cdb5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610c999190611116565b6020604051808303815f875af1158015610cb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd991906111f4565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610d27919061127f565b925050819055508160065f828254610d3f919061127f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610da3919061103f565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610dfc919061124c565b925050819055508060065f828254610e14919061124c565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610e78919061103f565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610ebb578082015181840152602081019050610ea0565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610ee082610e84565b610eea8185610e8e565b9350610efa818560208601610e9e565b610f0381610ec6565b840191505092915050565b5f6020820190508181035f830152610f268184610ed6565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610f5b82610f32565b9050919050565b610f6b81610f51565b8114610f75575f80fd5b50565b5f81359050610f8681610f62565b92915050565b5f819050919050565b610f9e81610f8c565b8114610fa8575f80fd5b50565b5f81359050610fb981610f95565b92915050565b5f8060408385031215610fd557610fd4610f2e565b5b5f610fe285828601610f78565b9250506020610ff385828601610fab565b9150509250929050565b5f8115159050919050565b61101181610ffd565b82525050565b5f60208201905061102a5f830184611008565b92915050565b61103981610f8c565b82525050565b5f6020820190506110525f830184611030565b92915050565b5f805f6060848603121561106f5761106e610f2e565b5b5f61107c86828701610f78565b935050602061108d86828701610f78565b925050604061109e86828701610fab565b9150509250925092565b5f60ff82169050919050565b6110bd816110a8565b82525050565b5f6020820190506110d65f8301846110b4565b92915050565b5f602082840312156110f1576110f0610f2e565b5b5f6110fe84828501610f78565b91505092915050565b61111081610f51565b82525050565b5f6020820190506111295f830184611107565b92915050565b5f806040838503121561114557611144610f2e565b5b5f61115285828601610f78565b925050602061116385828601610f78565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806111b157607f821691505b6020821081036111c4576111c361116d565b5b50919050565b6111d381610ffd565b81146111dd575f80fd5b50565b5f815190506111ee816111ca565b92915050565b5f6020828403121561120957611208610f2e565b5b5f611216848285016111e0565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61125682610f8c565b915061126183610f8c565b92508282039050818111156112795761127861121f565b5b92915050565b5f61128982610f8c565b915061129483610f8c565b92508282019050808211156112ac576112ab61121f565b5b9291505056fea26469706673582212200d99d18248e83d210e18f23ff87e4eb89c4a2794c313c7d44e6df4c88a1bb1f964736f6c63430008180033a2646970667358221220104aed2e81c5fa422cb7af2267fdb086a78076322eb92fe4b1fb0bc7f603365c64736f6c63430008180033", + Bin: "0x608060405234801561000f575f80fd5b506124018061001d5f395ff3fe608060405234801562000010575f80fd5b50600436106200002c575f3560e01c806306ef1a861462000030575b5f80fd5b6200004e6004803603810190620000489190620003a5565b62000066565b6040516200005d91906200047f565b60405180910390f35b5f808484846040516200007990620001f3565b62000087939291906200052f565b604051809103905ff080158015620000a1573d5f803e3d5ffd5b50905060f273ffffffffffffffffffffffffffffffffffffffff1663d126274a826040518263ffffffff1660e01b8152600401620000e091906200047f565b6020604051808303815f875af1158015620000fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001239190620005b2565b508073ffffffffffffffffffffffffffffffffffffffff1663f2fde38b336040518263ffffffff1660e01b81526004016200015f91906200047f565b5f604051808303815f87803b15801562000177575f80fd5b505af11580156200018a573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f85e892981b234101136bc30081e0a5c44345bebc0940193230c20a43b279e2d160405160405180910390a3809150509392505050565b611de980620005e383390190565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b62000262826200021a565b810181811067ffffffffffffffff821117156200028457620002836200022a565b5b80604052505050565b5f6200029862000201565b9050620002a6828262000257565b919050565b5f67ffffffffffffffff821115620002c857620002c76200022a565b5b620002d3826200021a565b9050602081019050919050565b828183375f83830152505050565b5f62000304620002fe84620002ab565b6200028d565b90508281526020810184848401111562000323576200032262000216565b5b62000330848285620002e0565b509392505050565b5f82601f8301126200034f576200034e62000212565b5b813562000361848260208601620002ee565b91505092915050565b5f60ff82169050919050565b62000381816200036a565b81146200038c575f80fd5b50565b5f813590506200039f8162000376565b92915050565b5f805f60608486031215620003bf57620003be6200020a565b5b5f84013567ffffffffffffffff811115620003df57620003de6200020e565b5b620003ed8682870162000338565b935050602084013567ffffffffffffffff8111156200041157620004106200020e565b5b6200041f8682870162000338565b925050604062000432868287016200038f565b9150509250925092565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000467826200043c565b9050919050565b62000479816200045b565b82525050565b5f602082019050620004945f8301846200046e565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015620004d3578082015181840152602081019050620004b6565b5f8484015250505050565b5f620004ea826200049a565b620004f68185620004a4565b935062000508818560208601620004b4565b62000513816200021a565b840191505092915050565b62000529816200036a565b82525050565b5f6060820190508181035f830152620005498186620004de565b905081810360208301526200055f8185620004de565b90506200057060408301846200051e565b949350505050565b5f8115159050919050565b6200058e8162000578565b811462000599575f80fd5b50565b5f81519050620005ac8162000583565b92915050565b5f60208284031215620005ca57620005c96200020a565b5b5f620005d9848285016200059c565b9150509291505056fe608060405234801562000010575f80fd5b5060405162001de938038062001de983398181016040528101906200003691906200027c565b335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600390816200008691906200054a565b5081600490816200009891906200054a565b508060055f6101000a81548160ff021916908360ff1602179055505050506200062e565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200011d82620000d5565b810181811067ffffffffffffffff821117156200013f576200013e620000e5565b5b80604052505050565b5f62000153620000bc565b905062000161828262000112565b919050565b5f67ffffffffffffffff821115620001835762000182620000e5565b5b6200018e82620000d5565b9050602081019050919050565b5f5b83811015620001ba5780820151818401526020810190506200019d565b5f8484015250505050565b5f620001db620001d58462000166565b62000148565b905082815260208101848484011115620001fa57620001f9620000d1565b5b620002078482856200019b565b509392505050565b5f82601f830112620002265762000225620000cd565b5b815162000238848260208601620001c5565b91505092915050565b5f60ff82169050919050565b620002588162000241565b811462000263575f80fd5b50565b5f8151905062000276816200024d565b92915050565b5f805f60608486031215620002965762000295620000c5565b5b5f84015167ffffffffffffffff811115620002b657620002b5620000c9565b5b620002c4868287016200020f565b935050602084015167ffffffffffffffff811115620002e857620002e7620000c9565b5b620002f6868287016200020f565b9250506040620003098682870162000266565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200036257607f821691505b6020821081036200037857620003776200031d565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003dc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200039f565b620003e886836200039f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004326200042c620004268462000400565b62000409565b62000400565b9050919050565b5f819050919050565b6200044d8362000412565b620004656200045c8262000439565b848454620003ab565b825550505050565b5f90565b6200047b6200046d565b6200048881848462000442565b505050565b5b81811015620004af57620004a35f8262000471565b6001810190506200048e565b5050565b601f821115620004fe57620004c8816200037e565b620004d38462000390565b81016020851015620004e3578190505b620004fb620004f28562000390565b8301826200048d565b50505b505050565b5f82821c905092915050565b5f620005205f198460080262000503565b1980831691505092915050565b5f6200053a83836200050f565b9150826002028217905092915050565b620005558262000313565b67ffffffffffffffff811115620005715762000570620000e5565b5b6200057d82546200034a565b6200058a828285620004b3565b5f60209050601f831160018114620005c0575f8415620005ab578287015190505b620005b785826200052d565b86555062000626565b601f198416620005d0866200037e565b5f5b82811015620005f957848901518255600182019150602085019450602081019050620005d2565b8683101562000619578489015162000615601f8916826200050f565b8355505b6001600288020188555050505b505050505050565b6117ad806200063c5f395ff3fe608060405234801561000f575f80fd5b50600436106100fe575f3560e01c806370a0823111610095578063a9059cbb11610064578063a9059cbb14610298578063dd62ed3e146102c8578063f2fde38b146102f8578063fe1195ec14610314576100fe565b806370a08231146102105780638da5cb5b1461024057806395d89b411461025e5780639dc29fac1461027c576100fe565b806323b872dd116100d157806323b872dd1461018a5780632d688ca8146101ba578063313ce567146101d657806340c10f19146101f4576100fe565b806306fdde0314610102578063095ea7b31461012057806318160ddd146101505780631988513b1461016e575b5f80fd5b61010a610330565b604051610117919061120d565b60405180910390f35b61013a600480360381019061013591906112be565b6103bc565b6040516101479190611316565b60405180910390f35b6101586104a9565b604051610165919061133e565b60405180910390f35b61018860048036038101906101839190611357565b6104af565b005b6101a4600480360381019061019f9190611357565b61052e565b6040516101b19190611316565b60405180910390f35b6101d460048036038101906101cf91906112be565b61068e565b005b6101de61070b565b6040516101eb91906113c2565b60405180910390f35b61020e600480360381019061020991906112be565b61071d565b005b61022a600480360381019061022591906113db565b61083c565b604051610237919061133e565b60405180910390f35b610248610851565b6040516102559190611415565b60405180910390f35b610266610874565b604051610273919061120d565b60405180910390f35b610296600480360381019061029191906112be565b610900565b005b6102b260048036038101906102ad91906112be565b610a1f565b6040516102bf9190611316565b60405180910390f35b6102e260048036038101906102dd919061142e565b610af0565b6040516102ef919061133e565b60405180910390f35b610312600480360381019061030d91906113db565b610b10565b005b61032e600480360381019061032991906112be565b610c58565b005b6003805461033d90611499565b80601f016020809104026020016040519081016040528092919081815260200182805461036990611499565b80156103b45780601f1061038b576101008083540402835291602001916103b4565b820191905f5260205f20905b81548152906001019060200180831161039757829003601f168201915b505050505081565b5f8160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610497919061133e565b60405180910390a36001905092915050565b60065481565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590611513565b60405180910390fd5b610529838383610cd5565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b815260040161056a9190611415565b602060405180830381865afa158015610585573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a9919061155b565b156105e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e0906115f6565b60405180910390fd5b8260025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546106709190611641565b92505081905550610682858585610cd5565b60019150509392505050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f490611513565b60405180910390fd5b6107078282610ee0565b5050565b60055f9054906101000a900460ff1681565b8160f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b81526004016107589190611415565b602060405180830381865afa158015610773573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610797919061155b565b156107d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ce906116be565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461082d575f80fd5b6108378383610ee0565b505050565b6001602052805f5260405f205f915090505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6004805461088190611499565b80601f01602080910402602001604051908101604052809291908181526020018280546108ad90611499565b80156108f85780601f106108cf576101008083540402835291602001916108f8565b820191905f5260205f20905b8154815290600101906020018083116108db57829003601f168201915b505050505081565b8160f173ffffffffffffffffffffffffffffffffffffffff166360dc402f826040518263ffffffff1660e01b815260040161093b9190611415565b602060405180830381865afa158015610956573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061097a919061155b565b156109ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b190611726565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a10575f80fd5b610a1a83836110af565b505050565b5f8260f173ffffffffffffffffffffffffffffffffffffffff1663f2af9ac9826040518263ffffffff1660e01b8152600401610a5b9190611415565b602060405180830381865afa158015610a76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9a919061155b565b15610ada576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad1906115f6565b60405180910390fd5b610ae5338585610cd5565b600191505092915050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b66575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b9d575f80fd5b8073ffffffffffffffffffffffffffffffffffffffff165f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cbe90611513565b60405180910390fd5b610cd182826110af565b5050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610d109190611415565b602060405180830381865afa158015610d2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4f919061155b565b610dcf5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610d8d9190611415565b6020604051808303815f875af1158015610da9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dcd919061155b565b505b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e1b9190611641565b925050819055508160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e6e9190611744565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ed2919061133e565b60405180910390a350505050565b8160f273ffffffffffffffffffffffffffffffffffffffff16634e25ab64826040518263ffffffff1660e01b8152600401610f1b9190611415565b602060405180830381865afa158015610f36573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5a919061155b565b610fda5760f273ffffffffffffffffffffffffffffffffffffffff1663ceeae52a826040518263ffffffff1660e01b8152600401610f989190611415565b6020604051808303815f875af1158015610fb4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fd8919061155b565b505b8160015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110269190611744565b925050819055508160065f82825461103e9190611744565b925050819055508273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516110a2919061133e565b60405180910390a3505050565b8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110fb9190611641565b925050819055508060065f8282546111139190611641565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611177919061133e565b60405180910390a35050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156111ba57808201518184015260208101905061119f565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6111df82611183565b6111e9818561118d565b93506111f981856020860161119d565b611202816111c5565b840191505092915050565b5f6020820190508181035f83015261122581846111d5565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61125a82611231565b9050919050565b61126a81611250565b8114611274575f80fd5b50565b5f8135905061128581611261565b92915050565b5f819050919050565b61129d8161128b565b81146112a7575f80fd5b50565b5f813590506112b881611294565b92915050565b5f80604083850312156112d4576112d361122d565b5b5f6112e185828601611277565b92505060206112f2858286016112aa565b9150509250929050565b5f8115159050919050565b611310816112fc565b82525050565b5f6020820190506113295f830184611307565b92915050565b6113388161128b565b82525050565b5f6020820190506113515f83018461132f565b92915050565b5f805f6060848603121561136e5761136d61122d565b5b5f61137b86828701611277565b935050602061138c86828701611277565b925050604061139d868287016112aa565b9150509250925092565b5f60ff82169050919050565b6113bc816113a7565b82525050565b5f6020820190506113d55f8301846113b3565b92915050565b5f602082840312156113f0576113ef61122d565b5b5f6113fd84828501611277565b91505092915050565b61140f81611250565b82525050565b5f6020820190506114285f830184611406565b92915050565b5f80604083850312156114445761144361122d565b5b5f61145185828601611277565b925050602061146285828601611277565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806114b057607f821691505b6020821081036114c3576114c261146c565b5b50919050565b7f45524332303a2063616c6c6572206973206e6f742074686520636861696e00005f82015250565b5f6114fd601e8361118d565b9150611508826114c9565b602082019050919050565b5f6020820190508181035f83015261152a816114f1565b9050919050565b61153a816112fc565b8114611544575f80fd5b50565b5f8151905061155581611531565b92915050565b5f602082840312156115705761156f61122d565b5b5f61157d84828501611547565b91505092915050565b7f45524332303a207472616e7366657220746f20626c6f636b65642061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f6115e060228361118d565b91506115eb82611586565b604082019050919050565b5f6020820190508181035f83015261160d816115d4565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61164b8261128b565b91506116568361128b565b925082820390508181111561166e5761166d611614565b5b92915050565b7f45524332303a206d696e7420746f20626c6f636b6564206164647265737300005f82015250565b5f6116a8601e8361118d565b91506116b382611674565b602082019050919050565b5f6020820190508181035f8301526116d58161169c565b9050919050565b7f45524332303a206275726e2066726f6d206d6f64756c652061646472657373005f82015250565b5f611710601f8361118d565b915061171b826116dc565b602082019050919050565b5f6020820190508181035f83015261173d81611704565b9050919050565b5f61174e8261128b565b91506117598361128b565b925082820190508082111561177157611770611614565b5b9291505056fea26469706673582212200b811e3223eb1f009f52b242d4bf732a6b5ece5baaf4b10f1dcd217cee86754a64736f6c63430008180033a26469706673582212201d63c5a0d1e08b5ecfe9a4d8bebe6a0b6a293211efb245d9c67c98367f8879f064736f6c63430008180033", } // Erc20FactoryABI is the input ABI used to generate the binding from. diff --git a/x/evm/contracts/erc20_factory/ERC20Factory.sol b/x/evm/contracts/erc20_factory/ERC20Factory.sol index fd6bcf1..256e1b9 100644 --- a/x/evm/contracts/erc20_factory/ERC20Factory.sol +++ b/x/evm/contracts/erc20_factory/ERC20Factory.sol @@ -13,7 +13,7 @@ contract ERC20Factory is ERC20Registry { uint8 decimals ) external returns (address) { ERC20 erc20 = new ERC20(name, symbol, decimals); - + // register the ERC20 contract with the ERC20 registry ERC20_REGISTRY_CONTRACT.register_erc20_from_factory(address(erc20)); @@ -23,4 +23,4 @@ contract ERC20Factory is ERC20Registry { emit ERC20Created(address(erc20), msg.sender); return address(erc20); } -} \ No newline at end of file +} diff --git a/x/evm/contracts/erc20_registry/ERC20Registry.go b/x/evm/contracts/erc20_registry/ERC20Registry.go index 1c04298..aa33a90 100644 --- a/x/evm/contracts/erc20_registry/ERC20Registry.go +++ b/x/evm/contracts/erc20_registry/ERC20Registry.go @@ -32,7 +32,7 @@ var ( // Erc20RegistryMetaData contains all meta data concerning the Erc20Registry contract. var Erc20RegistryMetaData = &bind.MetaData{ ABI: "[]", - Bin: "0x6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea2646970667358221220c802e40a4afa60da789a5d872a091e646d00a323e178e0e14735ead4c5341a3764736f6c63430008180033", + Bin: "0x6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea26469706673582212203334da44d9942138944b21288eb47737e3fa0f320ba83d5b36d61f53ae69101664736f6c63430008180033", } // Erc20RegistryABI is the input ABI used to generate the binding from. diff --git a/x/evm/contracts/erc20_registry/ERC20Registry.sol b/x/evm/contracts/erc20_registry/ERC20Registry.sol index a7610cd..962efc4 100644 --- a/x/evm/contracts/erc20_registry/ERC20Registry.sol +++ b/x/evm/contracts/erc20_registry/ERC20Registry.sol @@ -14,14 +14,8 @@ contract ERC20Registry { } modifier register_erc20_store(address account) { - if ( - !ERC20_REGISTRY_CONTRACT.is_erc20_store_registered( - account - ) - ) { - ERC20_REGISTRY_CONTRACT.register_erc20_store( - account - ); + if (!ERC20_REGISTRY_CONTRACT.is_erc20_store_registered(account)) { + ERC20_REGISTRY_CONTRACT.register_erc20_store(account); } _; diff --git a/x/evm/contracts/i_cosmos/ICosmos.go b/x/evm/contracts/i_cosmos/ICosmos.go index abd6155..be536d3 100644 --- a/x/evm/contracts/i_cosmos/ICosmos.go +++ b/x/evm/contracts/i_cosmos/ICosmos.go @@ -31,7 +31,7 @@ var ( // ICosmosMetaData contains all meta data concerning the ICosmos contract. var ICosmosMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"msg\",\"type\":\"string\"}],\"name\":\"execute_cosmos\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"dummy\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"path\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"req\",\"type\":\"string\"}],\"name\":\"query_cosmos\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"result\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"evm_address\",\"type\":\"address\"}],\"name\":\"to_cosmos_address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"cosmos_address\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"erc20_address\",\"type\":\"address\"}],\"name\":\"to_denom\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"}],\"name\":\"to_erc20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"erc20_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"cosmos_address\",\"type\":\"string\"}],\"name\":\"to_evm_address\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"evm_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"msg\",\"type\":\"string\"}],\"name\":\"execute_cosmos\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"dummy\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"is_blocked_address\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"blocked\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"is_module_address\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"module\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"path\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"req\",\"type\":\"string\"}],\"name\":\"query_cosmos\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"result\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"evm_address\",\"type\":\"address\"}],\"name\":\"to_cosmos_address\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"cosmos_address\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"erc20_address\",\"type\":\"address\"}],\"name\":\"to_denom\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"}],\"name\":\"to_erc20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"erc20_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"cosmos_address\",\"type\":\"string\"}],\"name\":\"to_evm_address\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"evm_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // ICosmosABI is the input ABI used to generate the binding from. @@ -180,6 +180,68 @@ func (_ICosmos *ICosmosTransactorRaw) Transact(opts *bind.TransactOpts, method s return _ICosmos.Contract.contract.Transact(opts, method, params...) } +// IsBlockedAddress is a free data retrieval call binding the contract method 0xf2af9ac9. +// +// Solidity: function is_blocked_address(address account) view returns(bool blocked) +func (_ICosmos *ICosmosCaller) IsBlockedAddress(opts *bind.CallOpts, account common.Address) (bool, error) { + var out []interface{} + err := _ICosmos.contract.Call(opts, &out, "is_blocked_address", account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsBlockedAddress is a free data retrieval call binding the contract method 0xf2af9ac9. +// +// Solidity: function is_blocked_address(address account) view returns(bool blocked) +func (_ICosmos *ICosmosSession) IsBlockedAddress(account common.Address) (bool, error) { + return _ICosmos.Contract.IsBlockedAddress(&_ICosmos.CallOpts, account) +} + +// IsBlockedAddress is a free data retrieval call binding the contract method 0xf2af9ac9. +// +// Solidity: function is_blocked_address(address account) view returns(bool blocked) +func (_ICosmos *ICosmosCallerSession) IsBlockedAddress(account common.Address) (bool, error) { + return _ICosmos.Contract.IsBlockedAddress(&_ICosmos.CallOpts, account) +} + +// IsModuleAddress is a free data retrieval call binding the contract method 0x60dc402f. +// +// Solidity: function is_module_address(address account) view returns(bool module) +func (_ICosmos *ICosmosCaller) IsModuleAddress(opts *bind.CallOpts, account common.Address) (bool, error) { + var out []interface{} + err := _ICosmos.contract.Call(opts, &out, "is_module_address", account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsModuleAddress is a free data retrieval call binding the contract method 0x60dc402f. +// +// Solidity: function is_module_address(address account) view returns(bool module) +func (_ICosmos *ICosmosSession) IsModuleAddress(account common.Address) (bool, error) { + return _ICosmos.Contract.IsModuleAddress(&_ICosmos.CallOpts, account) +} + +// IsModuleAddress is a free data retrieval call binding the contract method 0x60dc402f. +// +// Solidity: function is_module_address(address account) view returns(bool module) +func (_ICosmos *ICosmosCallerSession) IsModuleAddress(account common.Address) (bool, error) { + return _ICosmos.Contract.IsModuleAddress(&_ICosmos.CallOpts, account) +} + // ExecuteCosmos is a paid mutator transaction binding the contract method 0xd46f64e6. // // Solidity: function execute_cosmos(string msg) returns(bool dummy) diff --git a/x/evm/contracts/i_cosmos/ICosmos.sol b/x/evm/contracts/i_cosmos/ICosmos.sol index e1e7923..eaa420f 100644 --- a/x/evm/contracts/i_cosmos/ICosmos.sol +++ b/x/evm/contracts/i_cosmos/ICosmos.sol @@ -8,6 +8,12 @@ address constant COSMOS_ADDRESS = 0x00000000000000000000000000000000000000f1; ICosmos constant COSMOS_CONTRACT = ICosmos(COSMOS_ADDRESS); interface ICosmos { + // check if an address is blocked in bank module + function is_blocked_address(address account) external view returns (bool blocked); + + // check if an address is a module account + function is_module_address(address account) external view returns (bool module); + // convert an EVM address to a Cosmos address function to_cosmos_address( address evm_address diff --git a/x/evm/contracts/i_erc20/IERC20.go b/x/evm/contracts/i_erc20/IERC20.go index f435766..6e42239 100644 --- a/x/evm/contracts/i_erc20/IERC20.go +++ b/x/evm/contracts/i_erc20/IERC20.go @@ -31,7 +31,7 @@ var ( // 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\"}]", + 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\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sudoTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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. @@ -387,6 +387,27 @@ func (_IErc20 *IErc20TransactorSession) Approve(spender common.Address, amount * return _IErc20.Contract.Approve(&_IErc20.TransactOpts, spender, amount) } +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_IErc20 *IErc20Transactor) SudoTransfer(opts *bind.TransactOpts, sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.contract.Transact(opts, "sudoTransfer", sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_IErc20 *IErc20Session) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.SudoTransfer(&_IErc20.TransactOpts, sender, recipient, amount) +} + +// SudoTransfer is a paid mutator transaction binding the contract method 0x1988513b. +// +// Solidity: function sudoTransfer(address sender, address recipient, uint256 amount) returns() +func (_IErc20 *IErc20TransactorSession) SudoTransfer(sender common.Address, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _IErc20.Contract.SudoTransfer(&_IErc20.TransactOpts, sender, recipient, amount) +} + // Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. // // Solidity: function transfer(address recipient, uint256 amount) returns(bool) diff --git a/x/evm/contracts/i_erc20/IERC20.sol b/x/evm/contracts/i_erc20/IERC20.sol index 17bd22b..73e6106 100644 --- a/x/evm/contracts/i_erc20/IERC20.sol +++ b/x/evm/contracts/i_erc20/IERC20.sol @@ -22,4 +22,11 @@ interface IERC20 { address recipient, uint256 amount ) external returns (bool); + + // Custom ERC20 contracts also should have sudo transfer method + function sudoTransfer( + address sender, + address recipient, + uint256 amount + ) external; } diff --git a/x/evm/keeper/address_test.go b/x/evm/keeper/address_test.go index e8a4794..99eb5f9 100644 --- a/x/evm/keeper/address_test.go +++ b/x/evm/keeper/address_test.go @@ -30,7 +30,7 @@ func Test_AllowLongCosmosAddress(t *testing.T) { 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, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) // mint native coin err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( diff --git a/x/evm/keeper/common_test.go b/x/evm/keeper/common_test.go index e3f7755..da2cca3 100644 --- a/x/evm/keeper/common_test.go +++ b/x/evm/keeper/common_test.go @@ -258,6 +258,7 @@ func _createTestInput( appCodec, runtime.NewKVStoreService(keys[evmtypes.StoreKey]), accountKeeper, + bankKeeper, communityPoolKeeper, msgRouter, queryRouter, diff --git a/x/evm/keeper/context.go b/x/evm/keeper/context.go index 6375378..a2d6daf 100644 --- a/x/evm/keeper/context.go +++ b/x/evm/keeper/context.go @@ -3,7 +3,6 @@ package keeper import ( "context" "encoding/json" - "fmt" "math" "math/big" @@ -390,7 +389,6 @@ func (k Keeper) dispatchMessages(ctx context.Context, msgs []sdk.Msg) error { // and execute it res, err := handler(sdkCtx, msg) if err != nil { - fmt.Println(err) return err } diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 936f451..7d55826 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -71,7 +71,7 @@ func (k ERC20Keeper) BurnCoins(ctx context.Context, addr sdk.AccAddress, amount return err } - inputBz, err := k.ERC20ABI.Pack("burn", evmAddr, coin.Amount.BigInt()) + inputBz, err := k.ERC20ABI.Pack("sudoBurn", evmAddr, coin.Amount.BigInt()) if err != nil { return types.ErrFailedToPackABI.Wrap(err.Error()) } @@ -327,7 +327,7 @@ func (k ERC20Keeper) MintCoins(ctx context.Context, addr sdk.AccAddress, amount if err != nil { return err } - inputBz, err := k.ERC20ABI.Pack("mint", evmAddr, coin.Amount.BigInt()) + inputBz, err := k.ERC20ABI.Pack("sudoMint", evmAddr, coin.Amount.BigInt()) if err != nil { return types.ErrFailedToPackABI.Wrap(err.Error()) } @@ -359,13 +359,13 @@ func (k ERC20Keeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toA return err } - inputBz, err := k.ERC20ABI.Pack("transfer", evmToAddr, coin.Amount.BigInt()) + inputBz, err := k.ERC20ABI.Pack("sudoTransfer", evmFromAddr, evmToAddr, coin.Amount.BigInt()) if err != nil { return types.ErrFailedToPackABI.Wrap(err.Error()) } // ignore the return values - _, _, err = k.EVMCall(ctx, evmFromAddr, contractAddr, inputBz) + _, _, err = k.EVMCall(ctx, types.StdAddress, contractAddr, inputBz) if err != nil { return err } diff --git a/x/evm/keeper/erc20_stores.go b/x/evm/keeper/erc20_stores.go index d553428..b8f2ca8 100644 --- a/x/evm/keeper/erc20_stores.go +++ b/x/evm/keeper/erc20_stores.go @@ -56,6 +56,12 @@ func (k ERC20StoresKeeper) Register(ctx context.Context, contractAddr common.Add return types.ErrCustomERC20NotAllowed } + if found, err := k.ERC20s.Has(ctx, contractAddr.Bytes()); err != nil { + return err + } else if found { + return nil + } + // default action is to allow all custom erc20s // but if allowedCustomERC20s is set, only allow those if len(params.AllowedCustomERC20s) > 0 { @@ -68,12 +74,6 @@ func (k ERC20StoresKeeper) Register(ctx context.Context, contractAddr common.Add } } - if found, err := k.ERC20s.Has(ctx, contractAddr.Bytes()); err != nil { - return err - } else if found { - return nil - } - return k.ERC20s.Set(ctx, contractAddr.Bytes()) } diff --git a/x/evm/keeper/erc20_test.go b/x/evm/keeper/erc20_test.go index 265c6ec..6370e19 100644 --- a/x/evm/keeper/erc20_test.go +++ b/x/evm/keeper/erc20_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" 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" "github.com/initia-labs/minievm/x/evm/contracts/erc20" @@ -29,7 +30,25 @@ func deployERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller common return common.BytesToAddress(ret[12:]) } -func mintERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, recipient common.Address, amount sdk.Coin) { +func burnERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, from common.Address, amount sdk.Coin, expectErr bool) { + abi, err := erc20.Erc20MetaData.GetAbi() + require.NoError(t, err) + + inputBz, err := abi.Pack("burn", from, 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) + if expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } +} + +func mintERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, recipient common.Address, amount sdk.Coin, expectErr bool) { abi, err := erc20.Erc20MetaData.GetAbi() require.NoError(t, err) @@ -40,7 +59,99 @@ func mintERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, recipie require.NoError(t, err) _, _, err = input.EVMKeeper.EVMCall(ctx, caller, erc20ContractAddr, inputBz) + if expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } +} + +func transferERC20(t *testing.T, ctx sdk.Context, input TestKeepers, caller, recipient common.Address, amount sdk.Coin, expectErr bool) { + abi, err := erc20.Erc20MetaData.GetAbi() + require.NoError(t, err) + + inputBz, err := abi.Pack("transfer", 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) + if expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + +} + +func Test_TransferToModuleAccount(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + _, _, addr := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + + input.Faucet.Fund(ctx, addr, sdk.NewCoin("foo", math.NewInt(100))) + + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + transferERC20(t, ctx, input, evmAddr, common.BytesToAddress(feeCollectorAddr.Bytes()), sdk.NewCoin("foo", math.NewInt(50)), true) + + _, _, addr2 := keyPubAddr() + evmAddr2 := common.BytesToAddress(addr2.Bytes()) + transferERC20(t, ctx, input, evmAddr, evmAddr2, sdk.NewCoin("foo", math.NewInt(50)), false) +} + +func Test_MintToModuleAccount(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + _, _, addr := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + + // 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) + + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + mintERC20(t, ctx, input, evmAddr, common.BytesToAddress(feeCollectorAddr.Bytes()), sdk.NewCoin(fooDenom, math.NewInt(50)), true) + + _, _, addr2 := keyPubAddr() + evmAddr2 := common.BytesToAddress(addr2.Bytes()) + mintERC20(t, ctx, input, evmAddr, evmAddr2, sdk.NewCoin(fooDenom, math.NewInt(50)), false) +} + +func Test_BurnFromModuleAccount(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + // register fee collector module account + input.AccountKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName) + + _, _, addr := keyPubAddr() + evmAddr := common.BytesToAddress(addr.Bytes()) + _, _, addr2 := keyPubAddr() + 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 coins + feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName) + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) + erc20Keeper.SendCoins(ctx, addr, feeCollectorAddr, sdk.NewCoins(sdk.NewCoin(fooDenom, math.NewInt(50)))) + erc20Keeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewCoin(fooDenom, math.NewInt(50)))) + + // should not be able to burn from module account + burnERC20(t, ctx, input, evmAddr, common.BytesToAddress(feeCollectorAddr.Bytes()), sdk.NewCoin(fooDenom, math.NewInt(50)), true) + + // should be able to burn from other account + burnERC20(t, ctx, input, evmAddr, evmAddr2, sdk.NewCoin(fooDenom, math.NewInt(50)), false) } func Test_MintBurn(t *testing.T) { @@ -72,7 +183,7 @@ func Test_MintBurn(t *testing.T) { require.NoError(t, err) // mint erc20 - mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100))) + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) amount, err := erc20Keeper.GetBalance(ctx, addr, "bar") require.NoError(t, err) @@ -151,7 +262,7 @@ func Test_GetSupply(t *testing.T) { 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, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) // mint native coin err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( @@ -255,8 +366,8 @@ func Test_IterateAccountBalances(t *testing.T) { 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))) + mintERC20(t, ctx, input, evmAddr, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) + mintERC20(t, ctx, input, evmAddr, evmAddr2, sdk.NewCoin(fooDenom, math.NewInt(200)), false) // mint native coin err = erc20Keeper.MintCoins(ctx, addr, sdk.NewCoins( diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 514cde6..83cdf3b 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -22,6 +22,7 @@ type Keeper struct { storeService corestoretypes.KVStoreService accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper communityPoolKeeper types.CommunityPoolKeeper erc20Keeper types.IERC20Keeper erc20StoresKeeper types.IERC20StoresKeeper @@ -62,6 +63,7 @@ func NewKeeper( cdc codec.Codec, storeService corestoretypes.KVStoreService, accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, communityPoolKeeper types.CommunityPoolKeeper, msgRouter baseapp.MessageRouter, grpcRouter *baseapp.GRPCQueryRouter, @@ -81,6 +83,7 @@ func NewKeeper( storeService: storeService, accountKeeper: accountKeeper, + bankKeeper: bankKeeper, communityPoolKeeper: communityPoolKeeper, msgRouter: msgRouter, diff --git a/x/evm/keeper/precompiles.go b/x/evm/keeper/precompiles.go index d2504b0..cd1a844 100644 --- a/x/evm/keeper/precompiles.go +++ b/x/evm/keeper/precompiles.go @@ -28,6 +28,7 @@ func (k *Keeper) loadPrecompiles() error { k.cdc, k.ac, k.accountKeeper, + k.bankKeeper, k, k.grpcRouter, k.queryCosmosWhitelist, diff --git a/x/evm/keeper/query_server_test.go b/x/evm/keeper/query_server_test.go index a288532..879e124 100644 --- a/x/evm/keeper/query_server_test.go +++ b/x/evm/keeper/query_server_test.go @@ -29,7 +29,7 @@ func Test_Query_Call(t *testing.T) { 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, evmAddr, sdk.NewCoin(fooDenom, math.NewInt(100)), false) abi, err := erc20.Erc20MetaData.GetAbi() require.NoError(t, err) diff --git a/x/evm/precompiles/cosmos/contract.go b/x/evm/precompiles/cosmos/contract.go index 5f055e1..6e7d59c 100644 --- a/x/evm/precompiles/cosmos/contract.go +++ b/x/evm/precompiles/cosmos/contract.go @@ -34,6 +34,7 @@ type CosmosPrecompile struct { ac address.Codec ak types.AccountKeeper + bk types.BankKeeper edk types.ERC20DenomKeeper grpcRouter types.GRPCRouter @@ -44,6 +45,7 @@ func NewCosmosPrecompile( cdc codec.Codec, ac address.Codec, ak types.AccountKeeper, + bk types.BankKeeper, edk types.ERC20DenomKeeper, grpcRouter types.GRPCRouter, queryWhitelist types.QueryCosmosWhitelist, @@ -58,6 +60,7 @@ func NewCosmosPrecompile( cdc: cdc, ac: ac, ak: ak, + bk: bk, edk: edk, grpcRouter: grpcRouter, queryWhitelist: queryWhitelist, @@ -69,6 +72,20 @@ func (e CosmosPrecompile) WithContext(ctx context.Context) vm.PrecompiledContrac return e } +func (e CosmosPrecompile) originAddress(ctx context.Context, addrBz []byte) (sdk.AccAddress, error) { + account := e.ak.GetAccount(ctx, addrBz) + if shorthandCallerAccount, ok := account.(types.ShorthandAccountI); ok { + addr, err := shorthandCallerAccount.GetOriginalAddress(e.ac) + if err != nil { + return nil, types.ErrPrecompileFailed.Wrap(err.Error()) + } + + addrBz = addr.Bytes() + } + + return addrBz, nil +} + // ExtendedRun implements vm.ExtendedPrecompiledContract. func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppliedGas uint64, readOnly bool) (resBz []byte, usedGas uint64, err error) { method, err := e.ABI.MethodById(input) @@ -87,6 +104,50 @@ func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppl ctx.GasMeter().ConsumeGas(storetypes.Gas(len(input))*GAS_PER_BYTE, "input bytes") switch method.Name { + case METHOD_IS_BLOCKED_ADDRESS: + ctx.GasMeter().ConsumeGas(IS_BLOCKED_ADDRESS_GAS, "is_blocked_address") + + var isBlockedAddressArguments IsBlockedAddressArguments + if err := method.Inputs.Copy(&isBlockedAddressArguments, args); err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } + + // convert shorthand account to original address + addr, err := e.originAddress(ctx, isBlockedAddressArguments.Address.Bytes()) + if err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } + + isBlocked := e.bk.BlockedAddr(addr) + + // abi encode the response + resBz, err = method.Outputs.Pack(isBlocked) + if err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } + case METHOD_IS_MODULE_ADDRESS: + ctx.GasMeter().ConsumeGas(IS_MODULE_ADDRESS_GAS, "is_blocked_address") + + var isModuleAddressArguments IsModuleAddressArguments + if err := method.Inputs.Copy(&isModuleAddressArguments, args); err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } + + // convert shorthand account to original address + addr, err := e.originAddress(ctx, isModuleAddressArguments.Address.Bytes()) + if err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } + + // check if the address is a module account + account := e.ak.GetAccount(ctx, addr) + _, isModuleAccount := account.(sdk.ModuleAccountI) + + // abi encode the response + resBz, err = method.Outputs.Pack(isModuleAccount) + if err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) + } case METHOD_TO_COSMOS_ADDRESS: ctx.GasMeter().ConsumeGas(TO_COSMOS_ADDRESS_GAS, "to_cosmos_address") @@ -151,18 +212,10 @@ func (e CosmosPrecompile) ExtendedRun(caller vm.ContractRef, input []byte, suppl return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) } - callerAddr := caller.Address().Bytes() - callerAccount := e.ak.GetAccount(ctx, callerAddr) - - // if the caller is a shorthand account, then use shorthand account's original address - // as the caller address. - if shorthandCallerAccount, ok := callerAccount.(types.ShorthandAccountI); ok { - addr, err := shorthandCallerAccount.GetOriginalAddress(e.ac) - if err != nil { - return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) - } - - callerAddr = addr.Bytes() + // convert shorthand account to original address + callerAddr, err := e.originAddress(ctx, caller.Address().Bytes()) + if err != nil { + return nil, ctx.GasMeter().GasConsumedToLimit(), types.ErrPrecompileFailed.Wrap(err.Error()) } for _, signer := range signers { diff --git a/x/evm/precompiles/cosmos/contract_test.go b/x/evm/precompiles/cosmos/contract_test.go index 18a88f4..0cc1b83 100644 --- a/x/evm/precompiles/cosmos/contract_test.go +++ b/x/evm/precompiles/cosmos/contract_test.go @@ -38,7 +38,7 @@ import ( oracletypes "github.com/skip-mev/slinky/x/oracle/types" ) -func setup() (sdk.Context, codec.Codec, address.Codec, types.AccountKeeper) { +func setup() (sdk.Context, codec.Codec, address.Codec, types.AccountKeeper, types.BankKeeper) { kv := db.NewMemDB() cms := store.NewCommitMultiStore(kv, log.NewNopLogger(), storemetrics.NewNoOpMetrics()) @@ -56,13 +56,107 @@ func setup() (sdk.Context, codec.Codec, address.Codec, types.AccountKeeper) { cdc := codec.NewProtoCodec(interfaceRegistry) ac := codecaddress.NewBech32Codec("init") - return ctx, cdc, ac, &MockAccountKeeper{accounts: make(map[string]sdk.AccountI)} + return ctx, cdc, ac, + &MockAccountKeeper{ac: ac, accounts: make(map[string]sdk.AccountI)}, + &MockBankKeeper{ac: ac, blockedAddresses: make(map[string]bool)} +} + +func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) { + ctx, cdc, ac, ak, bk := setup() + + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) + + cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + + evmAddr := common.HexToAddress("0x1") + cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) + require.NoError(t, err) + + abi, err := contracts.ICosmosMetaData.GetAbi() + require.NoError(t, err) + + // is blocked address + inputBz, err := abi.Pack(precompiles.METHOD_IS_BLOCKED_ADDRESS, evmAddr) + require.NoError(t, err) + + // out of gas panic + require.Panics(t, func() { + _, _, _ = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_BLOCKED_ADDRESS_GAS-1, true) + }) + + retBz, _, err := cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_BLOCKED_ADDRESS_GAS+uint64(len(inputBz)), true) + require.NoError(t, err) + + ret, err := abi.Unpack(precompiles.METHOD_IS_BLOCKED_ADDRESS, retBz) + require.NoError(t, err) + require.False(t, ret[0].(bool)) + + // block address + bk.(*MockBankKeeper).blockedAddresses[cosmosAddr] = true + + // is blocked address + inputBz, err = abi.Pack(precompiles.METHOD_IS_BLOCKED_ADDRESS, evmAddr) + require.NoError(t, err) + + retBz, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_BLOCKED_ADDRESS_GAS+uint64(len(inputBz)), true) + require.NoError(t, err) + + ret, err = abi.Unpack(precompiles.METHOD_IS_BLOCKED_ADDRESS, retBz) + require.NoError(t, err) + require.True(t, ret[0].(bool)) +} + +func Test_CosmosPrecompile_IsModuleAddress(t *testing.T) { + ctx, cdc, ac, ak, bk := setup() + + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) + require.NoError(t, err) + + cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) + + evmAddr := common.HexToAddress("0x1") + cosmosAddr, err := ac.BytesToString(evmAddr.Bytes()) + require.NoError(t, err) + + abi, err := contracts.ICosmosMetaData.GetAbi() + require.NoError(t, err) + + // is module address + inputBz, err := abi.Pack(precompiles.METHOD_IS_MODULE_ADDRESS, evmAddr) + require.NoError(t, err) + + // out of gas panic + require.Panics(t, func() { + _, _, _ = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_MODULE_ADDRESS_GAS-1, true) + }) + + retBz, _, err := cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_MODULE_ADDRESS_GAS+uint64(len(inputBz)), true) + require.NoError(t, err) + + ret, err := abi.Unpack(precompiles.METHOD_IS_MODULE_ADDRESS, retBz) + require.NoError(t, err) + require.False(t, ret[0].(bool)) + + // module address + ak.(*MockAccountKeeper).accounts[cosmosAddr] = authtypes.NewEmptyModuleAccount("test") + + // is module address + inputBz, err = abi.Pack(precompiles.METHOD_IS_MODULE_ADDRESS, evmAddr) + require.NoError(t, err) + + retBz, _, err = cosmosPrecompile.ExtendedRun(vm.AccountRef(evmAddr), inputBz, precompiles.IS_MODULE_ADDRESS_GAS+uint64(len(inputBz)), true) + require.NoError(t, err) + + ret, err = abi.Unpack(precompiles.METHOD_IS_MODULE_ADDRESS, retBz) + require.NoError(t, err) + require.True(t, ret[0].(bool)) } func Test_CosmosPrecompile_ToCosmosAddress(t *testing.T) { - ctx, cdc, ac, ak := setup() + ctx, cdc, ac, ak, bk := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, nil, nil, nil) + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) @@ -92,8 +186,8 @@ func Test_CosmosPrecompile_ToCosmosAddress(t *testing.T) { } func Test_CosmosPrecompile_ToEVMAddress(t *testing.T) { - ctx, cdc, ac, ak := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, nil, nil, nil) + ctx, cdc, ac, ak, bk := setup() + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) @@ -123,8 +217,8 @@ func Test_CosmosPrecompile_ToEVMAddress(t *testing.T) { } func Test_ExecuteCosmos(t *testing.T) { - ctx, cdc, ac, ak := setup() - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, nil, nil, nil) + ctx, cdc, ac, ak, bk := setup() + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil) require.NoError(t, err) cosmosPrecompile = cosmosPrecompile.WithContext(ctx).(precompiles.CosmosPrecompile) @@ -191,7 +285,7 @@ func Test_ExecuteCosmos(t *testing.T) { } func Test_QueryCosmos(t *testing.T) { - ctx, cdc, ac, ak := setup() + ctx, cdc, ac, ak, bk := setup() queryPath := "/slinky.oracle.v1.Query/Prices" expectedRet := oracletypes.GetPricesResponse{ @@ -205,7 +299,7 @@ func Test_QueryCosmos(t *testing.T) { }, }, } - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, nil, MockGRPCRouter{ + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, MockGRPCRouter{ routes: map[string]baseapp.GRPCQueryHandler{ queryPath: func(ctx sdk.Context, req *abci.RequestQuery) (*abci.ResponseQuery, error) { resBz, err := cdc.Marshal(&expectedRet) @@ -259,12 +353,12 @@ func Test_QueryCosmos(t *testing.T) { } func Test_ToDenom(t *testing.T) { - ctx, cdc, ac, ak := setup() + ctx, cdc, ac, ak, bk := setup() erc20Addr := common.HexToAddress("0x123") denom := "evm/0000000000000000000000000000000000000123" - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, &MockERC20DenomKeeper{ + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, &MockERC20DenomKeeper{ denomMap: map[string]common.Address{ denom: erc20Addr, }, @@ -301,12 +395,12 @@ func Test_ToDenom(t *testing.T) { } func Test_ToErc20(t *testing.T) { - ctx, cdc, ac, ak := setup() + ctx, cdc, ac, ak, bk := setup() erc20Addr := common.HexToAddress("0x123") denom := "evm/0000000000000000000000000000000000000123" - cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, &MockERC20DenomKeeper{ + cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, &MockERC20DenomKeeper{ denomMap: map[string]common.Address{ denom: erc20Addr, }, @@ -346,17 +440,20 @@ var _ types.AccountKeeper = &MockAccountKeeper{} // mock account keeper for testing type MockAccountKeeper struct { + ac address.Codec accounts map[string]sdk.AccountI } // GetAccount implements types.AccountKeeper. func (k MockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { - return k.accounts[addr.String()] + str, _ := k.ac.BytesToString(addr.Bytes()) + return k.accounts[str] } // HasAccount implements types.AccountKeeper. func (k MockAccountKeeper) HasAccount(ctx context.Context, addr sdk.AccAddress) bool { - _, ok := k.accounts[addr.String()] + str, _ := k.ac.BytesToString(addr.Bytes()) + _, ok := k.accounts[str] return ok } @@ -378,7 +475,22 @@ func (k MockAccountKeeper) NextAccountNumber(ctx context.Context) uint64 { // SetAccount implements types.AccountKeeper. func (k MockAccountKeeper) SetAccount(ctx context.Context, acc sdk.AccountI) { - k.accounts[acc.GetAddress().String()] = acc + str, _ := k.ac.BytesToString(acc.GetAddress().Bytes()) + k.accounts[str] = acc +} + +var _ types.BankKeeper = &MockBankKeeper{} + +// mock bank keeper for testing +type MockBankKeeper struct { + ac address.Codec + blockedAddresses map[string]bool +} + +// BlockedAddr implements types.BankKeeper. +func (k MockBankKeeper) BlockedAddr(addr sdk.AccAddress) bool { + str, _ := k.ac.BytesToString(addr.Bytes()) + return k.blockedAddresses[str] } var _ types.GRPCRouter = MockGRPCRouter{} diff --git a/x/evm/precompiles/cosmos/types.go b/x/evm/precompiles/cosmos/types.go index 5b37d98..c1e88f0 100644 --- a/x/evm/precompiles/cosmos/types.go +++ b/x/evm/precompiles/cosmos/types.go @@ -6,6 +6,16 @@ import ( "github.com/ethereum/go-ethereum/common" ) +// IsBlockedAddressArguments is the arguments for the is_blocked_address method. +type IsBlockedAddressArguments struct { + Address common.Address `abi:"address"` +} + +// IsModuleAddressArguments is the arguments for the is_module_address method. +type IsModuleAddressArguments struct { + Address common.Address `abi:"address"` +} + // ToCosmosAddressArguments is the arguments for the to_cosmos_address method. type ToCosmosAddressArguments struct { EVMAddress common.Address `abi:"evm_address"` @@ -38,20 +48,30 @@ type ToERC20Arguments struct { } const ( + IS_BLOCKED_ADDRESS_GAS storetypes.Gas = 100 + IS_MODULE_ADDRESS_GAS storetypes.Gas = 200 + TO_COSMOS_ADDRESS_GAS storetypes.Gas = 200 TO_EVM_ADDRESS_GAS storetypes.Gas = 200 - TO_DENOM_GAS storetypes.Gas = 100 - TO_ERC20_GAS storetypes.Gas = 100 - EXECUTE_COSMOS_GAS storetypes.Gas = 200 - QUERY_COSMOS_GAS storetypes.Gas = 200 - GAS_PER_BYTE storetypes.Gas = 1 + + TO_DENOM_GAS storetypes.Gas = 100 + TO_ERC20_GAS storetypes.Gas = 100 + + EXECUTE_COSMOS_GAS storetypes.Gas = 200 + QUERY_COSMOS_GAS storetypes.Gas = 200 + GAS_PER_BYTE storetypes.Gas = 1 ) const ( + METHOD_IS_BLOCKED_ADDRESS = "is_blocked_address" + METHOD_IS_MODULE_ADDRESS = "is_module_address" + METHOD_TO_COSMOS_ADDRESS = "to_cosmos_address" METHOD_TO_EVM_ADDRESS = "to_evm_address" - METHOD_EXECUTE_COSMOS = "execute_cosmos" - METHOD_QUERY_COSMOS = "query_cosmos" - METHOD_TO_DENOM = "to_denom" - METHOD_TO_ERC20 = "to_erc20" + + METHOD_EXECUTE_COSMOS = "execute_cosmos" + METHOD_QUERY_COSMOS = "query_cosmos" + + METHOD_TO_DENOM = "to_denom" + METHOD_TO_ERC20 = "to_erc20" ) diff --git a/x/evm/types/expected_keeper.go b/x/evm/types/expected_keeper.go index bab7c4c..cecc63a 100644 --- a/x/evm/types/expected_keeper.go +++ b/x/evm/types/expected_keeper.go @@ -24,6 +24,11 @@ type AccountKeeper interface { NextAccountNumber(ctx context.Context) uint64 } +// BankKeeper is expected keeper for bank module +type BankKeeper interface { + BlockedAddr(addr sdk.AccAddress) bool +} + 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