From c1582ff5792dd3c5b6482b28c4db415f83ca2ed3 Mon Sep 17 00:00:00 2001 From: Axvn Date: Fri, 4 Mar 2022 16:39:17 +0100 Subject: [PATCH 1/3] Add new TransferType SemiFungibleTransfer handlers for ERC1155 --- chains/evm/chain.go | 2 ++ chains/evm/listener/event-handler.go | 45 +++++++++++++++++++++++++++ chains/evm/voter/message-handler.go | 27 ++++++++++++++++ chains/substrate/events.go | 11 +++++++ chains/substrate/listener/listener.go | 10 ++++++ config/chain/evm.go | 3 ++ e2e/evm-evm/example/app/app.go | 2 ++ relayer/message/message.go | 7 +++-- 8 files changed, 104 insertions(+), 3 deletions(-) diff --git a/chains/evm/chain.go b/chains/evm/chain.go index 6c018b8e..08c1f296 100644 --- a/chains/evm/chain.go +++ b/chains/evm/chain.go @@ -62,12 +62,14 @@ func SetupDefaultEVMChain(rawConfig map[string]interface{}, txFabric calls.TxFab eventHandler := listener.NewETHEventHandler(*bridgeContract) eventHandler.RegisterEventHandler(config.Erc20Handler, listener.Erc20EventHandler) + eventHandler.RegisterEventHandler(config.Erc1155Handler, listener.Erc1155EventHandler) eventHandler.RegisterEventHandler(config.Erc721Handler, listener.Erc721EventHandler) eventHandler.RegisterEventHandler(config.GenericHandler, listener.GenericEventHandler) evmListener := listener.NewEVMListener(client, eventHandler, common.HexToAddress(config.Bridge)) mh := voter.NewEVMMessageHandler(*bridgeContract) mh.RegisterMessageHandler(config.Erc20Handler, voter.ERC20MessageHandler) + mh.RegisterMessageHandler(config.Erc1155Handler, voter.ERC1155MessageHandler) mh.RegisterMessageHandler(config.Erc721Handler, voter.ERC721MessageHandler) mh.RegisterMessageHandler(config.GenericHandler, voter.GenericMessageHandler) diff --git a/chains/evm/listener/event-handler.go b/chains/evm/listener/event-handler.go index bde30d48..ef866c12 100644 --- a/chains/evm/listener/event-handler.go +++ b/chains/evm/listener/event-handler.go @@ -107,6 +107,51 @@ func Erc20EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.Re return message.NewMessage(sourceID, destId, nonce, resourceID, message.FungibleTransfer, payload, metadata), nil } +// Erc1155EventHandler converts data pulled from event logs into message +// handlerResponse can be an empty slice +func Erc1155EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { + if len(calldata) < 116 { + err := errors.New("invalid calldata length: less than 116 bytes") + return nil, err + } + + // @dev + // tokenId: first 32 bytes of calldata + tokenId := calldata[:32] + + // @dev + // amount: second 32 bytes of calldata + amount := calldata[32:64] + + // lenRecipientAddress: third 32 bytes of calldata [64:96] + // does not need to be derived because it is being calculated + // within ERC1155MessageHandler + // https://github.com/ChainSafe/chainbridge-core/blob/main/chains/evm/voter/message-handler.go#L108 + + // 32-64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[64:96]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddress := calldata[96:(96 + recipientAddressLength.Int64())] + // if there is priority data, parse it and use it + payload := []interface{}{ + tokenId, + amount, + recipientAddress, + } + + // arbitrary metadata that will be most likely be used by the relayer + var metadata message.Metadata + if 96+recipientAddressLength.Int64() < int64(len(calldata)) { + priorityLength := big.NewInt(0).SetBytes(calldata[(96 + recipientAddressLength.Int64()):((96 + recipientAddressLength.Int64()) + 1)]) + + // (64 + recipient address length + 1) - ((64 + recipient address length + 1) + priority length) is priority data + priority := calldata[(96 + recipientAddressLength.Int64() + 1):((96 + recipientAddressLength.Int64()) + 1 + priorityLength.Int64())] + metadata.Priority = priority[0] + } + return message.NewMessage(sourceID, destId, nonce, resourceID, message.SemiFungibleTransfer, payload, metadata), nil +} + // GenericEventHandler converts data pulled from generic deposit event logs into message func GenericEventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { if len(calldata) < 32 { diff --git a/chains/evm/voter/message-handler.go b/chains/evm/voter/message-handler.go index 1e8fb1cd..c8b33d8d 100644 --- a/chains/evm/voter/message-handler.go +++ b/chains/evm/voter/message-handler.go @@ -90,6 +90,33 @@ func ERC20MessageHandler(m *message.Message, handlerAddr, bridgeAddress common.A return proposal.NewProposal(m.Source, m.DepositNonce, m.ResourceId, data, handlerAddr, bridgeAddress, m.Metadata), nil } +// Same as ERC20, except the payload contains an extra integer for the tokenID +func ERC1155MessageHandler(m *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { + if len(m.Payload) != 3 { + return nil, errors.New("malformed payload. Len of payload should be 3") + } + tokenId, ok := m.Payload[0].([]byte) + if !ok { + return nil, errors.New("wrong payload tokenID format") + } + + amount, ok := m.Payload[1].([]byte) + if !ok { + return nil, errors.New("wrong payload amount format") + } + recipient, ok := m.Payload[2].([]byte) + if !ok { + return nil, errors.New("wrong payload recipient format") + } + var data []byte + data = append(data, common.LeftPadBytes(tokenId, 32)...) // tokenId (uint256) + data = append(data, common.LeftPadBytes(amount, 32)...) // amount (uint256) + recipientLen := big.NewInt(int64(len(recipient))).Bytes() + data = append(data, common.LeftPadBytes(recipientLen, 32)...) // length of recipient (uint256) + data = append(data, recipient...) // recipient ([]byte) + return proposal.NewProposal(m.Source, m.DepositNonce, m.ResourceId, data, handlerAddr, bridgeAddress, m.Metadata), nil +} + func ERC721MessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { if len(msg.Payload) != 3 { diff --git a/chains/substrate/events.go b/chains/substrate/events.go index 5a8f62d2..391de394 100644 --- a/chains/substrate/events.go +++ b/chains/substrate/events.go @@ -191,6 +191,16 @@ type EventFungibleTransfer struct { Topics []types.Hash } +type EventSemiFungibleTransfer struct { + Phase types.Phase + Destination types.U8 + DepositNonce types.U64 + ResourceId types.Bytes32 + TokenID types.U256 + Amount types.U256 + Recipient types.Bytes + Topics []types.Hash +} type EventNonFungibleTransfer struct { Phase types.Phase Destination types.U8 @@ -282,6 +292,7 @@ type EventProposalFailed struct { type Events struct { types.EventRecords ChainBridge_FungibleTransfer []EventFungibleTransfer //nolint:stylecheck,golint + ChainBridge_SemiFungibleTransfer []EventSemiFungibleTransfer //nolint:stylecheck,golint ChainBridge_NonFungibleTransfer []EventNonFungibleTransfer //nolint:stylecheck,golint ChainBridge_GenericTransfer []EventGenericTransfer //nolint:stylecheck,golint ChainBridge_RelayerThresholdChanged []EventRelayerThresholdChanged //nolint:stylecheck,golint diff --git a/chains/substrate/listener/listener.go b/chains/substrate/listener/listener.go index 633528c2..34a0564d 100644 --- a/chains/substrate/listener/listener.go +++ b/chains/substrate/listener/listener.go @@ -119,6 +119,16 @@ func (l *SubstrateListener) handleEvents(domainID uint8, evts *substrate.Events) msgs = append(msgs, m) } } + if l.eventHandlers[message.SemiFungibleTransfer] != nil { + for _, evt := range evts.ChainBridge_SemiFungibleTransfer { + m, err := l.eventHandlers[message.SemiFungibleTransfer](domainID, evt) + if err != nil { + return nil, err + } + msgs = append(msgs, m) + } + } + if l.eventHandlers[message.NonFungibleTransfer] != nil { for _, evt := range evts.ChainBridge_NonFungibleTransfer { m, err := l.eventHandlers[message.NonFungibleTransfer](domainID, evt) diff --git a/config/chain/evm.go b/config/chain/evm.go index 2e441d47..53c4df09 100644 --- a/config/chain/evm.go +++ b/config/chain/evm.go @@ -14,6 +14,7 @@ type EVMConfig struct { Bridge string Erc20Handler string Erc721Handler string + Erc1155Handler string GenericHandler string MaxGasPrice *big.Int GasMultiplier *big.Float @@ -28,6 +29,7 @@ type RawEVMConfig struct { Bridge string `mapstructure:"bridge"` Erc20Handler string `mapstructure:"erc20Handler"` Erc721Handler string `mapstructure:"erc721Handler"` + Erc1155Handler string `mapstructure:"erc1155Handler"` GenericHandler string `mapstructure:"genericHandler"` MaxGasPrice int64 `mapstructure:"maxGasPrice"` GasMultiplier float64 `mapstructure:"gasMultiplier"` @@ -69,6 +71,7 @@ func NewEVMConfig(chainConfig map[string]interface{}) (*EVMConfig, error) { GeneralChainConfig: c.GeneralChainConfig, Erc20Handler: c.Erc20Handler, Erc721Handler: c.Erc721Handler, + Erc1155Handler: c.Erc1155Handler, GenericHandler: c.GenericHandler, Bridge: c.Bridge, BlockRetryInterval: consts.DefaultBlockRetryInterval, diff --git a/e2e/evm-evm/example/app/app.go b/e2e/evm-evm/example/app/app.go index e83b0dcd..371555ee 100644 --- a/e2e/evm-evm/example/app/app.go +++ b/e2e/evm-evm/example/app/app.go @@ -67,12 +67,14 @@ func Run() error { eventHandler := listener.NewETHEventHandler(*bridgeContract) eventHandler.RegisterEventHandler(config.Erc20Handler, listener.Erc20EventHandler) + eventHandler.RegisterEventHandler(config.Erc1155Handler, listener.Erc1155EventHandler) eventHandler.RegisterEventHandler(config.Erc721Handler, listener.Erc721EventHandler) eventHandler.RegisterEventHandler(config.GenericHandler, listener.GenericEventHandler) evmListener := listener.NewEVMListener(client, eventHandler, common.HexToAddress(config.Bridge)) mh := voter.NewEVMMessageHandler(*bridgeContract) mh.RegisterMessageHandler(config.Erc20Handler, voter.ERC20MessageHandler) + mh.RegisterMessageHandler(config.Erc1155Handler, voter.ERC1155MessageHandler) mh.RegisterMessageHandler(config.Erc721Handler, voter.ERC721MessageHandler) mh.RegisterMessageHandler(config.GenericHandler, voter.GenericMessageHandler) diff --git a/relayer/message/message.go b/relayer/message/message.go index 587a0ebf..513023ad 100644 --- a/relayer/message/message.go +++ b/relayer/message/message.go @@ -17,9 +17,10 @@ type Metadata struct { } const ( - FungibleTransfer TransferType = "FungibleTransfer" - NonFungibleTransfer TransferType = "NonFungibleTransfer" - GenericTransfer TransferType = "GenericTransfer" + FungibleTransfer TransferType = "FungibleTransfer" + NonFungibleTransfer TransferType = "NonFungibleTransfer" + SemiFungibleTransfer TransferType = "SemiFungibleTransfer" + GenericTransfer TransferType = "GenericTransfer" ) type ProposalStatus struct { From 2baab65b943986f5047d1fef0ee997f1c3b673a1 Mon Sep 17 00:00:00 2001 From: Axvn Date: Sun, 20 Mar 2022 14:33:16 +0100 Subject: [PATCH 2/3] Add Event and Message handler tests --- chains/evm/calls/contracts/deposit/deposit.go | 17 +++ chains/evm/listener/event-handler_test.go | 126 ++++++++++++++++++ chains/evm/voter/message-handler_test.go | 112 +++++++++++++++- config/chain/evm_test.go | 2 + 4 files changed, 256 insertions(+), 1 deletion(-) diff --git a/chains/evm/calls/contracts/deposit/deposit.go b/chains/evm/calls/contracts/deposit/deposit.go index 67c889ee..50d07a5c 100644 --- a/chains/evm/calls/contracts/deposit/deposit.go +++ b/chains/evm/calls/contracts/deposit/deposit.go @@ -19,6 +19,13 @@ func ConstructErc20DepositData(destRecipient []byte, amount *big.Int) []byte { return data } +func ConstructErc1155DepositData(destRecipient []byte, tokenId *big.Int, amount *big.Int) []byte { + var data []byte + data = append(data, math.PaddedBigBytes(tokenId, 32)...) + data = append(data, constructMainDepositData(amount, destRecipient)...) + return data +} + func ConstructErc20DepositDataWithPriority(destRecipient []byte, amount *big.Int, priority uint8) []byte { data := constructMainDepositData(amount, destRecipient) data = append(data, math.PaddedBigBytes(big.NewInt(int64(len([]uint8{priority}))), 1)...) // Length of priority @@ -26,6 +33,16 @@ func ConstructErc20DepositDataWithPriority(destRecipient []byte, amount *big.Int return data } +func ConstructErc1155DepositDataWithPriority(destRecipient []byte, tokenId *big.Int, amount *big.Int, priority uint8) []byte { + var data []byte + data = append(data, math.PaddedBigBytes(tokenId, 32)...) + + data = append(data, constructMainDepositData(amount, destRecipient)...) + data = append(data, math.PaddedBigBytes(big.NewInt(int64(len([]uint8{priority}))), 1)...) // Length of priority + data = append(data, math.PaddedBigBytes(big.NewInt(int64(priority)), 1)...) // Priority + return data +} + func ConstructErc721DepositData(destRecipient []byte, tokenId *big.Int, metadata []byte) []byte { data := constructMainDepositData(tokenId, destRecipient) data = append(data, math.PaddedBigBytes(big.NewInt(int64(len(metadata))), 32)...) // Length of metadata diff --git a/chains/evm/listener/event-handler_test.go b/chains/evm/listener/event-handler_test.go index 2e7b5e5b..ca75ec0a 100644 --- a/chains/evm/listener/event-handler_test.go +++ b/chains/evm/listener/event-handler_test.go @@ -15,7 +15,9 @@ import ( ) var errIncorrectDataLen = errors.New("invalid calldata length: less than 84 bytes") +var errIncorrect1155DataLen = errors.New("invalid calldata length: less than 116 bytes") +// ERC20 type Erc20HandlerTestSuite struct { suite.Suite } @@ -133,6 +135,7 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEventIncorrectDataLen() { s.EqualError(err, errIncorrectDataLen.Error()) } +// ERC721 type Erc721HandlerTestSuite struct { suite.Suite } @@ -293,6 +296,129 @@ func (s *Erc721HandlerTestSuite) TestErc721EventHandlerWithPriority() { s.Equal(expected, m) } +// ERC1155 +type Erc1155HandlerTestSuite struct { + suite.Suite +} + +func TestRunErc1155HandlerTestSuite(t *testing.T) { + suite.Run(t, new(Erc1155HandlerTestSuite)) +} + +func (s *Erc1155HandlerTestSuite) SetupSuite() {} +func (s *Erc1155HandlerTestSuite) TearDownSuite() {} +func (s *Erc1155HandlerTestSuite) SetupTest() {} +func (s *Erc1155HandlerTestSuite) TearDownTest() {} + +func (s *Erc1155HandlerTestSuite) TestErc1155HandleEvent() { + // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b + recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} + + calldata := deposit.ConstructErc1155DepositData(recipientByteSlice, big.NewInt(2), big.NewInt(1)) + depositLog := &evmclient.DepositLogs{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + tokenId := calldata[:32] + amountParsed := calldata[32:64] + recipientAddressParsed := calldata[96:] + + expected := &message.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: message.SemiFungibleTransfer, + Payload: []interface{}{ + tokenId, + amountParsed, + recipientAddressParsed, + }, + } + + message, err := listener.Erc1155EventHandler(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *Erc1155HandlerTestSuite) TestErc1155HandleEventWithPriority() { + // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b + recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} + + calldata := deposit.ConstructErc1155DepositDataWithPriority(recipientByteSlice, big.NewInt(2), big.NewInt(1), uint8(1)) + depositLog := &evmclient.DepositLogs{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + tokenId := calldata[:32] + amountParsed := calldata[32:64] + // 32-64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[64:96]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddressParsed := calldata[96:(96 + recipientAddressLength.Int64())] + expected := &message.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: message.SemiFungibleTransfer, + Payload: []interface{}{ + tokenId, + amountParsed, + recipientAddressParsed, + }, + Metadata: message.Metadata{ + Priority: uint8(1), + }, + } + + message, err := listener.Erc1155EventHandler(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *Erc1155HandlerTestSuite) TestErc1155HandleEventIncorrectDataLen() { + metadata := []byte("0xdeadbeef") + + var calldata []byte + calldata = append(calldata, math.PaddedBigBytes(big.NewInt(int64(len(metadata))), 32)...) + calldata = append(calldata, metadata...) + + depositLog := &evmclient.DepositLogs{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + + message, err := listener.Erc1155EventHandler(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(message) + s.EqualError(err, errIncorrect1155DataLen.Error()) +} + +// Generic type GenericHandlerTestSuite struct { suite.Suite } diff --git a/chains/evm/voter/message-handler_test.go b/chains/evm/voter/message-handler_test.go index cdc3150d..38c80a35 100644 --- a/chains/evm/voter/message-handler_test.go +++ b/chains/evm/voter/message-handler_test.go @@ -2,16 +2,19 @@ package voter_test import ( "errors" + "github.com/ChainSafe/chainbridge-core/chains/evm/voter" + "testing" + "github.com/ChainSafe/chainbridge-core/relayer/message" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" - "testing" ) var errIncorrectERC20PayloadLen = errors.New("malformed payload. Len of payload should be 2") var errIncorrectERC721PayloadLen = errors.New("malformed payload. Len of payload should be 3") +var errIncorrectERC1155PayloadLen = errors.New("malformed payload. Len of payload should be 3") var errIncorrectGenericPayloadLen = errors.New("malformed payload. Len of payload should be 1") var errIncorrectAmount = errors.New("wrong payload amount format") @@ -254,6 +257,113 @@ func (s *Erc721HandlerTestSuite) TestErc721MessageHandlerIncorrectMetadata() { s.EqualError(err, errIncorrectMetadata.Error()) } +// ERC1155 +type Erc1155HandlerTestSuite struct { + suite.Suite +} + +func TestRunErc1155HandlerTestSuite(t *testing.T) { + suite.Run(t, new(Erc1155HandlerTestSuite)) +} + +func (s *Erc1155HandlerTestSuite) SetupSuite() {} +func (s *Erc1155HandlerTestSuite) TearDownSuite() {} +func (s *Erc1155HandlerTestSuite) SetupTest() {} +func (s *Erc1155HandlerTestSuite) TearDownTest() {} + +func (s *Erc1155HandlerTestSuite) TestErc1155MessageHandlerEmptyMetadata() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.SemiFungibleTransfer, + Payload: []interface{}{ + []byte{2}, // tokenID + []byte{1}, // amount + []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107}, // recipientAddress + }, + Metadata: message.Metadata{ + Priority: uint8(1), + }, + } + + prop, err := voter.ERC1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(err) + s.NotNil(prop) +} + +func (s *Erc1155HandlerTestSuite) TestErc1155MessageHandlerIncorrectDataLen() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []byte{2}, // tokenID + }, + Metadata: message.Metadata{ + Priority: uint8(1), + }, + } + + prop, err := voter.ERC1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.NotNil(err) + s.EqualError(err, errIncorrectERC1155PayloadLen.Error()) +} + +func (s *Erc1155HandlerTestSuite) TestErc1155MessageHandlerIncorrectAmount() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.SemiFungibleTransfer, + Payload: []interface{}{ + "incorrectAmount", // tokenID + []byte{1}, // amount + []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107}, // recipientAddress + }, + Metadata: message.Metadata{ + Priority: uint8(1), + }, + } + + prop, err := voter.ERC1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.NotNil(err) + s.EqualError(err, errIncorrectTokenID.Error()) +} + +func (s *Erc1155HandlerTestSuite) TestErc1155MessageHandlerIncorrectRecipient() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.SemiFungibleTransfer, + Payload: []interface{}{ + []byte{1}, // tokenId + []byte{2}, // amount + "incorrectRecipient", + }, + Metadata: message.Metadata{ + Priority: uint8(1), + }, + } + + prop, err := voter.ERC1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.NotNil(err) + s.EqualError(err, errIncorrectRecipient.Error()) +} + // GENERIC type GenericHandlerTestSuite struct { suite.Suite diff --git a/config/chain/evm_test.go b/config/chain/evm_test.go index 30f808c4..f2a369d3 100644 --- a/config/chain/evm_test.go +++ b/config/chain/evm_test.go @@ -86,6 +86,7 @@ func (s *NewEVMConfigTestSuite) Test_ValidConfig() { Bridge: "bridgeAddress", Erc20Handler: "", Erc721Handler: "", + Erc1155Handler: "", GenericHandler: "", GasLimit: big.NewInt(consts.DefaultGasLimit), MaxGasPrice: big.NewInt(consts.DefaultGasPrice), @@ -126,6 +127,7 @@ func (s *NewEVMConfigTestSuite) Test_ValidConfigWithCustomTxParams() { Bridge: "bridgeAddress", Erc20Handler: "", Erc721Handler: "", + Erc1155Handler: "", GenericHandler: "", GasLimit: big.NewInt(1000), MaxGasPrice: big.NewInt(1000), From c418dfc7c73478cae5a936dbbaa914c4ea5edf03 Mon Sep 17 00:00:00 2001 From: Axvn Date: Sun, 20 Mar 2022 16:02:02 +0100 Subject: [PATCH 3/3] Add ERC1155 handler ABI --- chains/evm/calls/consts/erc1155Hand.er.go | 4 + .../calls/consts/erc1155PresetMinterPauser.go | 4 + chains/evm/calls/contracts/erc1155/erc1155.go | 84 ++++++++++++ .../calls/contracts/erc1155/erc1155Handler.go | 26 ++++ .../calls/contracts/erc1155/erc1155_test.go | 121 ++++++++++++++++++ 5 files changed, 239 insertions(+) create mode 100644 chains/evm/calls/consts/erc1155Hand.er.go create mode 100644 chains/evm/calls/consts/erc1155PresetMinterPauser.go create mode 100644 chains/evm/calls/contracts/erc1155/erc1155.go create mode 100644 chains/evm/calls/contracts/erc1155/erc1155Handler.go create mode 100644 chains/evm/calls/contracts/erc1155/erc1155_test.go diff --git a/chains/evm/calls/consts/erc1155Hand.er.go b/chains/evm/calls/consts/erc1155Hand.er.go new file mode 100644 index 00000000..f16162ee --- /dev/null +++ b/chains/evm/calls/consts/erc1155Hand.er.go @@ -0,0 +1,4 @@ +package consts + +const ERC1155HandlerABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"bridgeAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"_bridgeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"_burnList\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"_contractWhitelist\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"_resourceIDToTokenContractAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"_tokenContractAddressToResourceID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"setBurnable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"resourceID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"setResource\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"constant\":true},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"resourceID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"depositer\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"metaData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"resourceID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"executeProposal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +const ERC1155HandlerBin = "0x60a060405234801561001057600080fd5b5060405161110938038061110983398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516110776100926000396000818161016a01526105cb01526110776000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80637f79bea81161008c578063bc197c8111610066578063bc197c8114610205578063c8ba6c871461023d578063e248cff21461026b578063f23a6e611461027e57600080fd5b80637f79bea8146101af578063b07e54bb146101d2578063b8fa3736146101f257600080fd5b806301ffc9a7146100d457806307b7ed99146100fc5780630968f264146101115780630a6d55d814610124578063318c136e146101655780636a70d0811461018c575b600080fd5b6100e76100e23660046108cf565b61029d565b60405190151581526020015b60405180910390f35b61010f61010a366004610915565b6102d4565b005b61010f61011f3660046109f7565b6102e8565b61014d610132366004610a34565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016100f3565b61014d7f000000000000000000000000000000000000000000000000000000000000000081565b6100e761019a366004610915565b60036020526000908152604090205460ff1681565b6100e76101bd366004610915565b60026020526000908152604090205460ff1681565b6101e56101e0366004610a96565b61032e565b6040516100f39190610b4e565b61010f610200366004610b61565b61041b565b610224610213366004610c1b565b63bc197c8160e01b95945050505050565b6040516001600160e01b031990911681526020016100f3565b61025d61024b366004610915565b60016020526000908152604090205481565b6040519081526020016100f3565b61010f610279366004610cc9565b610470565b61022461028c366004610d15565b63f23a6e6160e01b95945050505050565b60006001600160e01b03198216630271189760e51b14806102ce57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6102dc6105c0565b6102e58161063a565b50565b6102f06105c0565b60008060608060608580602001905181019061030c9190610dd9565b9398509196509450925090506103268530868686866106d2565b505050505050565b60606103386105c0565b60008061034784860186610ec5565b60008981526020819052604090205491935091506001600160a01b0316806103c15760405162461bcd60e51b815260206004820152602260248201527f70726f7669646564207265736f75726365494420646f6573206e6f74206578696044820152611cdd60f21b60648201526084015b60405180910390fd5b6001600160a01b03811660009081526003602052604090205460ff16156103f3576103ee81888585610743565b610410565b6104108188308686604051806020016040528060008152506107ac565b505050949350505050565b6104236105c0565b60008281526020818152604080832080546001600160a01b0319166001600160a01b039590951694851790559282526001808252838320949094556002905220805460ff19169091179055565b6104786105c0565b60008080606061048a85870187610ee7565b919550935091508560608661049f8583610f13565b926104ac93929190610f39565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508b81526020818152604080832054828801516001600160a01b039091168085526002909352922054959650909490935060ff16915061057090505760405162461bcd60e51b815260206004820152602860248201527f70726f766964656420746f6b656e41646472657373206973206e6f74207768696044820152671d195b1a5cdd195960c21b60648201526084016103b8565b6001600160a01b03811660009081526003602052604090205460ff16156105a5576105a0818360601c88886107e2565b6105b5565b6105b581308460601c898961083a565b505050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106385760405162461bcd60e51b815260206004820152601e60248201527f73656e646572206d7573742062652062726964676520636f6e7472616374000060448201526064016103b8565b565b6001600160a01b03811660009081526002602052604090205460ff166106ae5760405162461bcd60e51b8152602060048201526024808201527f70726f766964656420636f6e7472616374206973206e6f742077686974656c696044820152631cdd195960e21b60648201526084016103b8565b6001600160a01b03166000908152600360205260409020805460ff19166001179055565b604051631759616b60e11b815286906001600160a01b03821690632eb2c2d6906107089089908990899089908990600401610f9e565b600060405180830381600087803b15801561072257600080fd5b505af1158015610736573d6000803e3d6000fd5b5050505050505050505050565b604051637a94c56560e11b81526001600160a01b038481166004830152602482018490526044820183905285919082169063f5298aca906064015b600060405180830381600087803b15801561079857600080fd5b505af11580156105b5573d6000803e3d6000fd5b604051637921219560e11b815286906001600160a01b0382169063f242432a906107089089908990899089908990600401610ffc565b60405163731133e960e01b81526001600160a01b0384811660048301526024820184905260448201839052608060648301526002608483015261060f60f31b60a483015285919082169063731133e99060c40161077e565b604051637921219560e11b81526001600160a01b0385811660048301528481166024830152604482018490526064820183905260a06084830152600260a483015261060f60f31b60c483015286919082169063f242432a9060e401600060405180830381600087803b1580156108af57600080fd5b505af11580156108c3573d6000803e3d6000fd5b50505050505050505050565b6000602082840312156108e157600080fd5b81356001600160e01b0319811681146108f957600080fd5b9392505050565b6001600160a01b03811681146102e557600080fd5b60006020828403121561092757600080fd5b81356108f981610900565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561097157610971610932565b604052919050565b600067ffffffffffffffff82111561099357610993610932565b50601f01601f191660200190565b600082601f8301126109b257600080fd5b81356109c56109c082610979565b610948565b8181528460208386010111156109da57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215610a0957600080fd5b813567ffffffffffffffff811115610a2057600080fd5b610a2c848285016109a1565b949350505050565b600060208284031215610a4657600080fd5b5035919050565b60008083601f840112610a5f57600080fd5b50813567ffffffffffffffff811115610a7757600080fd5b602083019150836020828501011115610a8f57600080fd5b9250929050565b60008060008060608587031215610aac57600080fd5b843593506020850135610abe81610900565b9250604085013567ffffffffffffffff811115610ada57600080fd5b610ae687828801610a4d565b95989497509550505050565b60005b83811015610b0d578181015183820152602001610af5565b83811115610b1c576000848401525b50505050565b60008151808452610b3a816020860160208601610af2565b601f01601f19169290920160200192915050565b6020815260006108f96020830184610b22565b60008060408385031215610b7457600080fd5b823591506020830135610b8681610900565b809150509250929050565b600067ffffffffffffffff821115610bab57610bab610932565b5060051b60200190565b600082601f830112610bc657600080fd5b81356020610bd66109c083610b91565b82815260059290921b84018101918181019086841115610bf557600080fd5b8286015b84811015610c105780358352918301918301610bf9565b509695505050505050565b600080600080600060a08688031215610c3357600080fd5b8535610c3e81610900565b94506020860135610c4e81610900565b9350604086013567ffffffffffffffff80821115610c6b57600080fd5b610c7789838a01610bb5565b94506060880135915080821115610c8d57600080fd5b610c9989838a01610bb5565b93506080880135915080821115610caf57600080fd5b50610cbc888289016109a1565b9150509295509295909350565b600080600060408486031215610cde57600080fd5b83359250602084013567ffffffffffffffff811115610cfc57600080fd5b610d0886828701610a4d565b9497909650939450505050565b600080600080600060a08688031215610d2d57600080fd5b8535610d3881610900565b94506020860135610d4881610900565b93506040860135925060608601359150608086013567ffffffffffffffff811115610d7257600080fd5b610cbc888289016109a1565b600082601f830112610d8f57600080fd5b81516020610d9f6109c083610b91565b82815260059290921b84018101918181019086841115610dbe57600080fd5b8286015b84811015610c105780518352918301918301610dc2565b600080600080600060a08688031215610df157600080fd5b8551610dfc81610900565b6020870151909550610e0d81610900565b604087015190945067ffffffffffffffff80821115610e2b57600080fd5b610e3789838a01610d7e565b94506060880151915080821115610e4d57600080fd5b610e5989838a01610d7e565b93506080880151915080821115610e6f57600080fd5b508601601f81018813610e8157600080fd5b8051610e8f6109c082610979565b818152896020838501011115610ea457600080fd5b610eb5826020830160208601610af2565b8093505050509295509295909350565b60008060408385031215610ed857600080fd5b50508035926020909101359150565b600080600060608486031215610efc57600080fd5b505081359360208301359350604090920135919050565b60008219821115610f3457634e487b7160e01b600052601160045260246000fd5b500190565b60008085851115610f4957600080fd5b83861115610f5657600080fd5b5050820193919092039150565b600081518084526020808501945080840160005b83811015610f9357815187529582019590820190600101610f77565b509495945050505050565b6001600160a01b0386811682528516602082015260a060408201819052600090610fca90830186610f63565b8281036060840152610fdc8186610f63565b90508281036080840152610ff08185610b22565b98975050505050505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061103690830184610b22565b97965050505050505056fea26469706673582212203b1cf38ce674c76153c842e5c4fc04e03d0910f91d0c8e67aa6b8fab5d9c0bb964736f6c634300080b0033" diff --git a/chains/evm/calls/consts/erc1155PresetMinterPauser.go b/chains/evm/calls/consts/erc1155PresetMinterPauser.go new file mode 100644 index 00000000..60861ff8 --- /dev/null +++ b/chains/evm/calls/consts/erc1155PresetMinterPauser.go @@ -0,0 +1,4 @@ +package consts + +const ERC1155PresetMinterPauserABI = "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PAUSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"burnBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mintBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" +const ERC1155PresetMinterPauserBin = "0x60806040523480156200001157600080fd5b5060405162002d3c38038062002d3c8339810160408190526200003491620002e7565b806200004081620000b7565b506005805460ff1916905562000058600033620000d0565b620000847f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620000d0565b620000b07f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000d0565b5062000400565b8051620000cc9060049060208401906200022b565b5050565b620000cc8282620000ed82826200011960201b62000ad51760201c565b60008281526001602090815260409091206200011491839062000b59620001b9821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000cc576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001753390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001d0836001600160a01b038416620001d9565b90505b92915050565b60008181526001830160205260408120546200022257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001d3565b506000620001d3565b8280546200023990620003c3565b90600052602060002090601f0160209004810192826200025d5760008555620002a8565b82601f106200027857805160ff1916838001178555620002a8565b82800160010185558215620002a8579182015b82811115620002a85782518255916020019190600101906200028b565b50620002b6929150620002ba565b5090565b5b80821115620002b65760008155600101620002bb565b634e487b7160e01b600052604160045260246000fd5b60006020808385031215620002fb57600080fd5b82516001600160401b03808211156200031357600080fd5b818501915085601f8301126200032857600080fd5b8151818111156200033d576200033d620002d1565b604051601f8201601f19908116603f01168101908382118183101715620003685762000368620002d1565b8160405282815288868487010111156200038157600080fd5b600093505b82841015620003a5578484018601518185018701529285019262000386565b82841115620003b75760008684830101525b98975050505050505050565b600181811c90821680620003d857607f821691505b60208210811415620003fa57634e487b7160e01b600052602260045260246000fd5b50919050565b61292c80620004106000396000f3fe608060405234801561001057600080fd5b50600436106101725760003560e01c8063731133e9116100de578063ca15c87311610097578063e63ab1e911610071578063e63ab1e914610358578063e985e9c51461037f578063f242432a146103bb578063f5298aca146103ce57600080fd5b8063ca15c8731461030b578063d53913931461031e578063d547741f1461034557600080fd5b8063731133e9146102975780638456cb59146102aa5780639010d07c146102b257806391d14854146102dd578063a217fddf146102f0578063a22cb465146102f857600080fd5b80632f2ff15d116101305780632f2ff15d1461022b57806336568abe1461023e5780633f4ba83a146102515780634e1273f4146102595780635c975abb146102795780636b20c4541461028457600080fd5b8062fdd58e1461017757806301ffc9a71461019d5780630e89341c146101c05780631f7fdffa146101e0578063248a9ca3146101f55780632eb2c2d614610218575b600080fd5b61018a610185366004611cc2565b6103e1565b6040519081526020015b60405180910390f35b6101b06101ab366004611d05565b61047d565b6040519015158152602001610194565b6101d36101ce366004611d22565b610488565b6040516101949190611d93565b6101f36101ee366004611ef2565b61051c565b005b61018a610203366004611d22565b60009081526020819052604090206001015490565b6101f3610226366004611f8b565b610574565b6101f3610239366004612035565b61060b565b6101f361024c366004612035565b610636565b6101f36106b4565b61026c610267366004612061565b61075a565b6040516101949190612167565b60055460ff166101b0565b6101f361029236600461217a565b610884565b6101f36102a53660046121ee565b6108c7565b6101f3610919565b6102c56102c0366004612243565b6109bd565b6040516001600160a01b039091168152602001610194565b6101b06102eb366004612035565b6109dc565b61018a600081565b6101f3610306366004612265565b610a05565b61018a610319366004611d22565b610a10565b61018a7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6101f3610353366004612035565b610a27565b61018a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6101b061038d3660046122a1565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b6101f36103c93660046122cb565b610a4d565b6101f36103dc366004612330565b610a92565b60006001600160a01b0383166104525760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b5060008181526002602090815260408083206001600160a01b03861684529091529020545b92915050565b600061047782610b6e565b60606004805461049790612363565b80601f01602080910402602001604051908101604052809291908181526020018280546104c390612363565b80156105105780601f106104e557610100808354040283529160200191610510565b820191906000526020600020905b8154815290600101906020018083116104f357829003601f168201915b50505050509050919050565b6105467f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336109dc565b6105625760405162461bcd60e51b81526004016104499061239e565b61056e84848484610bae565b50505050565b6001600160a01b0385163314806105905750610590853361038d565b6105f75760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610449565b6106048585858585610d09565b5050505050565b6000828152602081905260409020600101546106278133610eb6565b6106318383610f1a565b505050565b6001600160a01b03811633146106a65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610449565b6106b08282610f3c565b5050565b6106de7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336109dc565b6107505760405162461bcd60e51b815260206004820152603b60248201527f455243313135355072657365744d696e7465725061757365723a206d7573742060448201527f686176652070617573657220726f6c6520746f20756e706175736500000000006064820152608401610449565b610758610f5e565b565b606081518351146107bf5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610449565b6000835167ffffffffffffffff8111156107db576107db611da6565b604051908082528060200260200182016040528015610804578160200160208202803683370190505b50905060005b845181101561087c5761084f858281518110610828576108286123fb565b6020026020010151858381518110610842576108426123fb565b60200260200101516103e1565b828281518110610861576108616123fb565b602090810291909101015261087581612427565b905061080a565b509392505050565b6001600160a01b0383163314806108a057506108a0833361038d565b6108bc5760405162461bcd60e51b815260040161044990612442565b610631838383610ff1565b6108f17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336109dc565b61090d5760405162461bcd60e51b81526004016104499061239e565b61056e84848484611182565b6109437f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336109dc565b6109b55760405162461bcd60e51b815260206004820152603960248201527f455243313135355072657365744d696e7465725061757365723a206d7573742060448201527f686176652070617573657220726f6c6520746f207061757365000000000000006064820152608401610449565b61075861125a565b60008281526001602052604081206109d590836112d5565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6106b03383836112e1565b6000818152600160205260408120610477906113c2565b600082815260208190526040902060010154610a438133610eb6565b6106318383610f3c565b6001600160a01b038516331480610a695750610a69853361038d565b610a855760405162461bcd60e51b815260040161044990612442565b61060485858585856113cc565b6001600160a01b038316331480610aae5750610aae833361038d565b610aca5760405162461bcd60e51b815260040161044990612442565b6106318383836114ed565b610adf82826109dc565b6106b0576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610b153390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109d5836001600160a01b0384166115f2565b60006001600160e01b03198216636cdb3d1360e11b1480610b9f57506001600160e01b031982166303a24d0760e21b145b80610477575061047782611641565b6001600160a01b038416610bd45760405162461bcd60e51b81526004016104499061248b565b8151835114610bf55760405162461bcd60e51b8152600401610449906124cc565b33610c0581600087878787611666565b60005b8451811015610ca157838181518110610c2357610c236123fb565b602002602001015160026000878481518110610c4157610c416123fb565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254610c899190612514565b90915550819050610c9981612427565b915050610c08565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610cf292919061252c565b60405180910390a461060481600087878787611674565b8151835114610d2a5760405162461bcd60e51b8152600401610449906124cc565b6001600160a01b038416610d505760405162461bcd60e51b81526004016104499061255a565b33610d5f818787878787611666565b60005b8451811015610e48576000858281518110610d7f57610d7f6123fb565b602002602001015190506000858381518110610d9d57610d9d6123fb565b60209081029190910181015160008481526002835260408082206001600160a01b038e168352909352919091205490915081811015610dee5760405162461bcd60e51b81526004016104499061259f565b60008381526002602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610e2d908490612514565b9250508190555050505080610e4190612427565b9050610d62565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610e9892919061252c565b60405180910390a4610eae818787878787611674565b505050505050565b610ec082826109dc565b6106b057610ed8816001600160a01b031660146117d0565b610ee38360206117d0565b604051602001610ef49291906125e9565b60408051601f198184030181529082905262461bcd60e51b825261044991600401611d93565b610f248282610ad5565b60008281526001602052604090206106319082610b59565b610f46828261196c565b600082815260016020526040902061063190826119d1565b60055460ff16610fa75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610449565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0383166110175760405162461bcd60e51b81526004016104499061265e565b80518251146110385760405162461bcd60e51b8152600401610449906124cc565b600033905061105b81856000868660405180602001604052806000815250611666565b60005b835181101561112357600084828151811061107b5761107b6123fb565b602002602001015190506000848381518110611099576110996123fb565b60209081029190910181015160008481526002835260408082206001600160a01b038c1683529093529190912054909150818110156110ea5760405162461bcd60e51b8152600401610449906126a1565b60009283526002602090815260408085206001600160a01b038b168652909152909220910390558061111b81612427565b91505061105e565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161117492919061252c565b60405180910390a450505050565b6001600160a01b0384166111a85760405162461bcd60e51b81526004016104499061248b565b336111c8816000876111b9886119e6565b6111c2886119e6565b87611666565b60008481526002602090815260408083206001600160a01b0389168452909152812080548592906111fa908490612514565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461060481600087878787611a31565b60055460ff16156112a05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610449565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610fd43390565b60006109d58383611aec565b816001600160a01b0316836001600160a01b031614156113555760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610449565b6001600160a01b03838116600081815260036020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000610477825490565b6001600160a01b0384166113f25760405162461bcd60e51b81526004016104499061255a565b336114028187876111b9886119e6565b60008481526002602090815260408083206001600160a01b038a168452909152902054838110156114455760405162461bcd60e51b81526004016104499061259f565b60008581526002602090815260408083206001600160a01b038b8116855292528083208785039055908816825281208054869290611484908490612514565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46114e4828888888888611a31565b50505050505050565b6001600160a01b0383166115135760405162461bcd60e51b81526004016104499061265e565b3361154281856000611524876119e6565b61152d876119e6565b60405180602001604052806000815250611666565b60008381526002602090815260408083206001600160a01b0388168452909152902054828110156115855760405162461bcd60e51b8152600401610449906126a1565b60008481526002602090815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b600081815260018301602052604081205461163957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610477565b506000610477565b60006001600160e01b03198216635a05180f60e01b1480610477575061047782611b16565b610eae868686868686611b4b565b6001600160a01b0384163b15610eae5760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906116b890899089908890889088906004016126e5565b6020604051808303816000875af19250505080156116f3575060408051601f3d908101601f191682019092526116f091810190612743565b60015b6117a0576116ff612760565b806308c379a01415611739575061171461277c565b8061171f575061173b565b8060405162461bcd60e51b81526004016104499190611d93565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610449565b6001600160e01b0319811663bc197c8160e01b146114e45760405162461bcd60e51b815260040161044990612806565b606060006117df83600261284e565b6117ea906002612514565b67ffffffffffffffff81111561180257611802611da6565b6040519080825280601f01601f19166020018201604052801561182c576020820181803683370190505b509050600360fc1b81600081518110611847576118476123fb565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611876576118766123fb565b60200101906001600160f81b031916908160001a905350600061189a84600261284e565b6118a5906001612514565b90505b600181111561191d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106118d9576118d96123fb565b1a60f81b8282815181106118ef576118ef6123fb565b60200101906001600160f81b031916908160001a90535060049490941c936119168161286d565b90506118a8565b5083156109d55760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610449565b61197682826109dc565b156106b0576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006109d5836001600160a01b038416611bb3565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110611a2057611a206123fb565b602090810291909101015292915050565b6001600160a01b0384163b15610eae5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611a759089908990889088908890600401612884565b6020604051808303816000875af1925050508015611ab0575060408051601f3d908101601f19168201909252611aad91810190612743565b60015b611abc576116ff612760565b6001600160e01b0319811663f23a6e6160e01b146114e45760405162461bcd60e51b815260040161044990612806565b6000826000018281548110611b0357611b036123fb565b9060005260206000200154905092915050565b60006001600160e01b03198216637965db0b60e01b148061047757506301ffc9a760e01b6001600160e01b0319831614610477565b60055460ff1615610eae5760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b6064820152608401610449565b60008181526001830160205260408120548015611c9c576000611bd76001836128c9565b8554909150600090611beb906001906128c9565b9050818114611c50576000866000018281548110611c0b57611c0b6123fb565b9060005260206000200154905080876000018481548110611c2e57611c2e6123fb565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c6157611c616128e0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610477565b6000915050610477565b80356001600160a01b0381168114611cbd57600080fd5b919050565b60008060408385031215611cd557600080fd5b611cde83611ca6565b946020939093013593505050565b6001600160e01b031981168114611d0257600080fd5b50565b600060208284031215611d1757600080fd5b81356109d581611cec565b600060208284031215611d3457600080fd5b5035919050565b60005b83811015611d56578181015183820152602001611d3e565b8381111561056e5750506000910152565b60008151808452611d7f816020860160208601611d3b565b601f01601f19169290920160200192915050565b6020815260006109d56020830184611d67565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715611de257611de2611da6565b6040525050565b600067ffffffffffffffff821115611e0357611e03611da6565b5060051b60200190565b600082601f830112611e1e57600080fd5b81356020611e2b82611de9565b604051611e388282611dbc565b83815260059390931b8501820192828101915086841115611e5857600080fd5b8286015b84811015611e735780358352918301918301611e5c565b509695505050505050565b600082601f830112611e8f57600080fd5b813567ffffffffffffffff811115611ea957611ea9611da6565b604051611ec0601f8301601f191660200182611dbc565b818152846020838601011115611ed557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611f0857600080fd5b611f1185611ca6565b9350602085013567ffffffffffffffff80821115611f2e57600080fd5b611f3a88838901611e0d565b94506040870135915080821115611f5057600080fd5b611f5c88838901611e0d565b93506060870135915080821115611f7257600080fd5b50611f7f87828801611e7e565b91505092959194509250565b600080600080600060a08688031215611fa357600080fd5b611fac86611ca6565b9450611fba60208701611ca6565b9350604086013567ffffffffffffffff80821115611fd757600080fd5b611fe389838a01611e0d565b94506060880135915080821115611ff957600080fd5b61200589838a01611e0d565b9350608088013591508082111561201b57600080fd5b5061202888828901611e7e565b9150509295509295909350565b6000806040838503121561204857600080fd5b8235915061205860208401611ca6565b90509250929050565b6000806040838503121561207457600080fd5b823567ffffffffffffffff8082111561208c57600080fd5b818501915085601f8301126120a057600080fd5b813560206120ad82611de9565b6040516120ba8282611dbc565b83815260059390931b85018201928281019150898411156120da57600080fd5b948201945b838610156120ff576120f086611ca6565b825294820194908201906120df565b9650508601359250508082111561211557600080fd5b5061212285828601611e0d565b9150509250929050565b600081518084526020808501945080840160005b8381101561215c57815187529582019590820190600101612140565b509495945050505050565b6020815260006109d5602083018461212c565b60008060006060848603121561218f57600080fd5b61219884611ca6565b9250602084013567ffffffffffffffff808211156121b557600080fd5b6121c187838801611e0d565b935060408601359150808211156121d757600080fd5b506121e486828701611e0d565b9150509250925092565b6000806000806080858703121561220457600080fd5b61220d85611ca6565b93506020850135925060408501359150606085013567ffffffffffffffff81111561223757600080fd5b611f7f87828801611e7e565b6000806040838503121561225657600080fd5b50508035926020909101359150565b6000806040838503121561227857600080fd5b61228183611ca6565b91506020830135801515811461229657600080fd5b809150509250929050565b600080604083850312156122b457600080fd5b6122bd83611ca6565b915061205860208401611ca6565b600080600080600060a086880312156122e357600080fd5b6122ec86611ca6565b94506122fa60208701611ca6565b93506040860135925060608601359150608086013567ffffffffffffffff81111561232457600080fd5b61202888828901611e7e565b60008060006060848603121561234557600080fd5b61234e84611ca6565b95602085013595506040909401359392505050565b600181811c9082168061237757607f821691505b6020821081141561239857634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526038908201527f455243313135355072657365744d696e7465725061757365723a206d7573742060408201527f68617665206d696e74657220726f6c6520746f206d696e740000000000000000606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141561243b5761243b612411565b5060010190565b60208082526029908201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260408201526808185c1c1c9bdd995960ba1b606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6000821982111561252757612527612411565b500190565b60408152600061253f604083018561212c565b8281036020840152612551818561212c565b95945050505050565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612621816017850160208801611d3b565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612652816028840160208801611d3b565b01602801949350505050565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b6001600160a01b0386811682528516602082015260a0604082018190526000906127119083018661212c565b8281036060840152612723818661212c565b905082810360808401526127378185611d67565b98975050505050505050565b60006020828403121561275557600080fd5b81516109d581611cec565b600060033d11156127795760046000803e5060005160e01c5b90565b600060443d101561278a5790565b6040516003193d81016004833e81513d67ffffffffffffffff81602484011181841117156127ba57505050505090565b82850191508151818111156127d25750505050505090565b843d87010160208285010111156127ec5750505050505090565b6127fb60208286010187611dbc565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b600081600019048311821515161561286857612868612411565b500290565b60008161287c5761287c612411565b506000190190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906128be90830184611d67565b979650505050505050565b6000828210156128db576128db612411565b500390565b634e487b7160e01b600052603160045260246000fdfea26469706673582212200a40d3d6b5c32249a30e18c213aa6e3b472006d3ebbe3acb415617c0bf2b54f164736f6c634300080b0033" diff --git a/chains/evm/calls/contracts/erc1155/erc1155.go b/chains/evm/calls/contracts/erc1155/erc1155.go new file mode 100644 index 00000000..e88b911c --- /dev/null +++ b/chains/evm/calls/contracts/erc1155/erc1155.go @@ -0,0 +1,84 @@ +package erc1155 + +import ( + "math/big" + "strings" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/consts" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog/log" +) + +type ERC1155Contract struct { + contracts.Contract +} + +func NewErc1155Contract( + client calls.ContractCallerDispatcher, + erc1155ContractAddress common.Address, + t transactor.Transactor, +) *ERC1155Contract { + a, _ := abi.JSON(strings.NewReader(consts.ERC1155PresetMinterPauserABI)) + b := common.FromHex(consts.ERC1155PresetMinterPauserBin) + return &ERC1155Contract{contracts.NewContract(erc1155ContractAddress, a, b, client, t)} +} + +func (c *ERC1155Contract) GetBalance(address common.Address, tokenId *big.Int) (*big.Int, error) { + log.Debug().Msgf("Getting balance for %s %s", address.String(), tokenId.String()) + res, err := c.CallContract("balanceOf", address, tokenId) + if err != nil { + return nil, err + } + b := abi.ConvertType(res[0], new(big.Int)).(*big.Int) + return b, nil +} + +func (c *ERC1155Contract) AddMinter( + minter common.Address, opts transactor.TransactOptions, +) (*common.Hash, error) { + log.Debug().Msgf("Adding new minter %s", minter.String()) + role, err := c.MinterRole() + if err != nil { + return nil, err + } + return c.ExecuteTransaction("grantRole", opts, role, minter) +} + +func (c *ERC1155Contract) Approve( + recipient common.Address, approved bool, opts transactor.TransactOptions, +) (*common.Hash, error) { + log.Debug().Msgf("Approving all token for %s", recipient.String()) + return c.ExecuteTransaction("setApprovalForAll", opts, recipient, approved) +} + +func (c *ERC1155Contract) Mint( + destination common.Address, tokenId *big.Int, amount *big.Int, data []byte, opts transactor.TransactOptions, +) (*common.Hash, error) { + log.Debug().Msgf("Minting tokens %s to %s", tokenId.String(), destination.String()) + return c.ExecuteTransaction("mint", opts, destination, tokenId, amount, data) +} + +func (c *ERC1155Contract) Owner(tokenId *big.Int) (*common.Address, error) { + log.Debug().Msgf("Getting owner of %s", tokenId.String()) + res, err := c.CallContract("ownerOf", tokenId) + if err != nil { + return nil, err + } + + ownerAddr := abi.ConvertType(res[0], new(common.Address)).(*common.Address) + return ownerAddr, nil +} + +func (c *ERC1155Contract) MinterRole() ([32]byte, error) { + res, err := c.CallContract("MINTER_ROLE") + if err != nil { + return [32]byte{}, err + } + out := *abi.ConvertType(res[0], new([32]byte)).(*[32]byte) + return out, nil +} diff --git a/chains/evm/calls/contracts/erc1155/erc1155Handler.go b/chains/evm/calls/contracts/erc1155/erc1155Handler.go new file mode 100644 index 00000000..073a877f --- /dev/null +++ b/chains/evm/calls/contracts/erc1155/erc1155Handler.go @@ -0,0 +1,26 @@ +package erc1155 + +import ( + "strings" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/consts" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +type ERC1155HandlerContract struct { + contracts.Contract +} + +func NewERC1155HandlerContract( + client calls.ContractCallerDispatcher, + erc1155HandlerContractAddress common.Address, + t transactor.Transactor, +) *ERC1155HandlerContract { + a, _ := abi.JSON(strings.NewReader(consts.ERC1155HandlerABI)) + b := common.FromHex(consts.ERC1155HandlerBin) + return &ERC1155HandlerContract{contracts.NewContract(erc1155HandlerContractAddress, a, b, client, t)} +} diff --git a/chains/evm/calls/contracts/erc1155/erc1155_test.go b/chains/evm/calls/contracts/erc1155/erc1155_test.go new file mode 100644 index 00000000..fe16f122 --- /dev/null +++ b/chains/evm/calls/contracts/erc1155/erc1155_test.go @@ -0,0 +1,121 @@ +package erc1155_test + +import ( + "math/big" + "testing" + + erc1155 "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/erc1155" + mock_calls "github.com/ChainSafe/chainbridge-core/chains/evm/calls/mock" + mock_transactor "github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor/mock" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor/signAndSend" + "github.com/ethereum/go-ethereum/common" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/suite" +) + +type ERC1155ContractCallsTestSuite struct { + suite.Suite + gomockController *gomock.Controller + mockContractCallerDispatcherClient *mock_calls.MockContractCallerDispatcher + mockTransactor *mock_transactor.MockTransactor + erc1155contract *erc1155.ERC1155Contract +} + +var ( + testContractAddress = "0x5f75ce92326e304962b22749bd71e36976171285" + testInteractorAddress = "0x8362bbbd6d987895E2A4630a55e69Dd8C7b9f87B" +) + +func TestRunERC1155ContractCallsTestSuite(t *testing.T) { + suite.Run(t, new(ERC1155ContractCallsTestSuite)) +} + +func (s *ERC1155ContractCallsTestSuite) SetupSuite() {} +func (s *ERC1155ContractCallsTestSuite) TearDownSuite() {} +func (s *ERC1155ContractCallsTestSuite) SetupTest() { + s.gomockController = gomock.NewController(s.T()) + s.mockContractCallerDispatcherClient = mock_calls.NewMockContractCallerDispatcher(s.gomockController) + s.mockTransactor = mock_transactor.NewMockTransactor(s.gomockController) + s.erc1155contract = erc1155.NewErc1155Contract( + s.mockContractCallerDispatcherClient, common.HexToAddress(testContractAddress), s.mockTransactor, + ) +} +func (s *ERC1155ContractCallsTestSuite) TearDownTest() {} + +func (s *ERC1155ContractCallsTestSuite) TestErc1155Contract_GetBalance_Success() { + s.mockContractCallerDispatcherClient.EXPECT().From().Return(common.HexToAddress(testInteractorAddress)) + s.mockContractCallerDispatcherClient.EXPECT().CallContract( + gomock.Any(), + gomock.Any(), + gomock.Any(), + ).Return([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, nil) + res, err := s.erc1155contract.GetBalance(common.HexToAddress(testInteractorAddress), big.NewInt(0)) + s.Equal( + big.NewInt(5), + res, + ) + s.Nil(err) +} + +func (s *ERC1155ContractCallsTestSuite) TestErc1155Contract_MintTokens_Success() { + s.mockTransactor.EXPECT().Transact( + gomock.Any(), + gomock.Any(), + gomock.Any(), + ).Return(&common.Hash{1, 2, 3, 4, 5}, nil) + res, err := s.erc1155contract.Mint(common.HexToAddress(testInteractorAddress), big.NewInt(0), big.NewInt(10), []byte("0x"), signAndSend.DefaultTransactionOptions) + s.Equal( + &common.Hash{1, 2, 3, 4, 5}, + res, + ) + s.Nil(err) +} + +func (s *ERC1155ContractCallsTestSuite) TestErc1155Contract_ApproveTokens_Success() { + s.mockTransactor.EXPECT().Transact( + gomock.Any(), + gomock.Any(), + gomock.Any(), + ).Return(&common.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9}, nil) + res, err := s.erc1155contract.Approve(common.HexToAddress(testInteractorAddress), true, signAndSend.DefaultTransactionOptions) + s.Equal( + &common.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9}, + res, + ) + s.Nil(err) +} + +func (s *ERC1155ContractCallsTestSuite) TestErc1155Contract_MinterRole_Success() { + s.mockContractCallerDispatcherClient.EXPECT().From().Return(common.HexToAddress(testInteractorAddress)) + s.mockContractCallerDispatcherClient.EXPECT().CallContract( + gomock.Any(), + gomock.Any(), + nil, + ).Return([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, nil) + res, err := s.erc1155contract.MinterRole() + s.Equal( + [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + res, + ) + s.Nil(err) +} + +func (s *ERC1155ContractCallsTestSuite) TestErc1155Contract_AddMinter_Success() { + s.mockContractCallerDispatcherClient.EXPECT().From().Return(common.HexToAddress(testInteractorAddress)) + s.mockContractCallerDispatcherClient.EXPECT().CallContract( + gomock.Any(), + gomock.Any(), + nil, + ).Return([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, nil) + s.mockTransactor.EXPECT().Transact( + gomock.Any(), + gomock.Any(), + gomock.Any(), + ).Return(&common.Hash{1, 2, 3}, nil) + res, err := s.erc1155contract.AddMinter(common.HexToAddress(testInteractorAddress), signAndSend.DefaultTransactionOptions) + s.Equal( + &common.Hash{1, 2, 3}, + res, + ) + s.Nil(err) +}