diff --git a/app/app.go b/app/app.go index 07fc68c3..df273198 100644 --- a/app/app.go +++ b/app/app.go @@ -199,6 +199,11 @@ func Run() error { depositHandler.RegisterDepositHandler(handler.Address, coreListener.Erc721DepositHandler) mh.RegisterMessageHandler(handler.Address, coreExecutor.ERC721MessageHandler) } + case "erc1155": + { + depositHandler.RegisterDepositHandler(handler.Address, listener.Erc1155DepositHandler) + mh.RegisterMessageHandler(handler.Address, executor.Erc1155MessageHandler) + } } } depositListener := coreEvents.NewListener(client) diff --git a/chains/evm/calls/consts/erc1155.go b/chains/evm/calls/consts/erc1155.go new file mode 100644 index 00000000..85169a9d --- /dev/null +++ b/chains/evm/calls/consts/erc1155.go @@ -0,0 +1,6 @@ +// The Licensed Work is (c) 2022 Sygma +// SPDX-License-Identifier: LGPL-3.0-only + +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":[{"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":"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]` diff --git a/chains/evm/calls/contracts/bridge/bridge.go b/chains/evm/calls/contracts/bridge/bridge.go index 4593efa8..9783db17 100644 --- a/chains/evm/calls/contracts/bridge/bridge.go +++ b/chains/evm/calls/contracts/bridge/bridge.go @@ -12,6 +12,8 @@ import ( "github.com/ChainSafe/chainbridge-core/chains/evm/calls" "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts" "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/deposit" + syg_deposit "github.com/ChainSafe/sygma-relayer/chains/evm/calls/contracts/deposit" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor" "github.com/ChainSafe/chainbridge-core/types" "github.com/ChainSafe/sygma-relayer/chains" @@ -128,6 +130,36 @@ func (c *BridgeContract) Erc721Deposit( return txHash, err } +func (c *BridgeContract) Erc1155Deposit( + tokenIds *big.Int, + amounts *big.Int, + metadata string, + recipient common.Address, + resourceID types.ResourceID, + destDomainID uint8, + feeData []byte, + opts transactor.TransactOptions, +) (*common.Hash, error) { + log.Debug(). + Str("recipient", recipient.String()). + Str("resourceID", hexutil.Encode(resourceID[:])). + Uint8("destDomainID", destDomainID). + Hex("feeData", feeData). + Msgf("ERC1155 deposit") + + var data []byte + data, err := syg_deposit.ConstructErc1155DepositData(recipient.Bytes(), tokenIds, amounts, []byte(metadata)) + if err != nil { + return nil, err + } + txHash, err := c.deposit(resourceID, destDomainID, data, feeData, opts) + if err != nil { + log.Error().Err(err) + return nil, err + } + return txHash, err +} + func (c *BridgeContract) GenericDeposit( metadata []byte, resourceID types.ResourceID, diff --git a/chains/evm/calls/contracts/deposit/deposit.go b/chains/evm/calls/contracts/deposit/deposit.go new file mode 100644 index 00000000..c147d06f --- /dev/null +++ b/chains/evm/calls/contracts/deposit/deposit.go @@ -0,0 +1,31 @@ +package deposit + +import ( + "math/big" + + "github.com/ChainSafe/sygma-relayer/chains/evm/listener" +) + +func ConstructErc1155DepositData(destRecipient []byte, tokenIds *big.Int, amounts *big.Int, metadata []byte) ([]byte, error) { + erc1155Type, err := listener.GetErc1155Type() + if err != nil { + return nil, err + } + + payload := []interface{}{ + []*big.Int{ + tokenIds, + }, + []*big.Int{ + amounts, + }, + destRecipient, + []byte{}, + } + data, err := erc1155Type.Pack(payload...) + + if err != nil { + return nil, err + } + return data, nil +} diff --git a/chains/evm/calls/contracts/erc1155/erc1155.go b/chains/evm/calls/contracts/erc1155/erc1155.go new file mode 100644 index 00000000..a412ca40 --- /dev/null +++ b/chains/evm/calls/contracts/erc1155/erc1155.go @@ -0,0 +1,53 @@ +package erc1155 + +import ( + "math/big" + "strings" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls" + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts" + "github.com/ChainSafe/sygma-relayer/chains/evm/calls/consts" + + "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.ERC1155PresetMinterPauserABI) + return &ERC1155Contract{contracts.NewContract(erc1155ContractAddress, a, b, client, t)} +} + +func (c *ERC1155Contract) Approve( + tokenId *big.Int, recipient common.Address, opts transactor.TransactOptions, +) (*common.Hash, error) { + log.Debug().Msgf("Approving %s token for %s", tokenId.String(), recipient.String()) + return c.ExecuteTransaction("setApprovalForAll", opts, recipient, true) +} + +func (c *ERC1155Contract) Mint( + tokenId *big.Int, amount *big.Int, metadata []byte, destination common.Address, 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, metadata) +} + +func (c *ERC1155Contract) BalanceOf(account common.Address, id *big.Int) (*big.Int, error) { + res, err := c.CallContract("balanceOf", account, id) + if err != nil { + return nil, err + } + + amount := abi.ConvertType(res[0], new(big.Int)).(*big.Int) + return amount, nil +} diff --git a/chains/evm/executor/message-handler.go b/chains/evm/executor/message-handler.go index fff76d0f..8e24f032 100644 --- a/chains/evm/executor/message-handler.go +++ b/chains/evm/executor/message-handler.go @@ -12,6 +12,7 @@ import ( "github.com/ChainSafe/chainbridge-core/chains/evm/executor/proposal" "github.com/ChainSafe/chainbridge-core/relayer/message" + "github.com/ChainSafe/sygma-relayer/chains/evm/listener" ) func PermissionlessGenericMessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { @@ -52,3 +53,41 @@ func PermissionlessGenericMessageHandler(msg *message.Message, handlerAddr, brid return proposal.NewProposal(msg.Source, msg.Destination, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress, msg.Metadata), nil } + +func Erc1155MessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { + + if len(msg.Payload) != 4 { + return nil, errors.New("malformed payload. Len of payload should be 4") + } + _, ok := msg.Payload[0].([]*big.Int) + if !ok { + return nil, errors.New("wrong payload tokenIDs format") + } + _, ok = msg.Payload[1].([]*big.Int) + if !ok { + return nil, errors.New("wrong payload amounts format") + } + _, ok = msg.Payload[2].([]byte) + if !ok { + return nil, errors.New("wrong payload recipient format") + } + if len(msg.Payload[2].([]byte)) != 20 { + return nil, errors.New("malformed payload. Len of recipient should be 20") + } + _, ok = msg.Payload[3].([]byte) + if !ok { + return nil, errors.New("wrong payload transferData format") + } + + erc1155Type, err := listener.GetErc1155Type() + if err != nil { + return nil, err + } + + data, err := erc1155Type.PackValues(msg.Payload) + if err != nil { + return nil, err + } + + return proposal.NewProposal(msg.Source, msg.Destination, msg.DepositNonce, msg.ResourceId, data, handlerAddr, bridgeAddress, msg.Metadata), nil +} diff --git a/chains/evm/executor/message-handler_test.go b/chains/evm/executor/message-handler_test.go index 846e00e5..1c99f471 100644 --- a/chains/evm/executor/message-handler_test.go +++ b/chains/evm/executor/message-handler_test.go @@ -5,6 +5,7 @@ package executor_test import ( "encoding/hex" + "errors" "math/big" "testing" @@ -19,6 +20,13 @@ import ( "github.com/stretchr/testify/suite" ) +var errIncorrectPayloadLen = errors.New("malformed payload. Len of payload should be 4") +var errIncorrectTokenIDs = errors.New("wrong payload tokenIDs format") +var errIncorrectAmounts = errors.New("wrong payload amounts format") +var errIncorrectRecipient = errors.New("wrong payload recipient format") +var errIncorrectRecipientLen = errors.New("malformed payload. Len of recipient should be 20") +var errIncorrectTransferData = errors.New("wrong payload transferData format") + type PermissionlessGenericHandlerTestSuite struct { suite.Suite } @@ -88,3 +96,187 @@ func (s *PermissionlessGenericHandlerTestSuite) Test_HandleMessage() { s.Nil(err) s.Equal(expected, prop) } + +// 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) Test_HandleErc1155Message() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + []byte{}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(err) + s.NotNil(prop) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidPayloadLen() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectPayloadLen.Error()) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidTokenIDs() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + 2, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + []byte{}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectTokenIDs.Error()) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidAmounts() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + 3, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + []byte{}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectAmounts.Error()) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidRecipient() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + "invalidRecipient", + []byte{}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectRecipient.Error()) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidRecipientLen() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251}, + []byte{}, + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectRecipientLen.Error()) +} + +func (s *Erc1155HandlerTestSuite) Test_HandleErc1155Message_InvalidTransferData() { + message := &message.Message{ + Source: 1, + Destination: 0, + DepositNonce: 1, + ResourceId: [32]byte{0}, + Type: message.FungibleTransfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + "invalidTransferData", + }, + } + + prop, err := executor.Erc1155MessageHandler(message, common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b")) + + s.Nil(prop) + s.EqualError(err, errIncorrectTransferData.Error()) +} diff --git a/chains/evm/listener/deposit-handler.go b/chains/evm/listener/deposit-handler.go index 1bd05a9b..356427ff 100644 --- a/chains/evm/listener/deposit-handler.go +++ b/chains/evm/listener/deposit-handler.go @@ -9,10 +9,12 @@ import ( "github.com/ChainSafe/chainbridge-core/relayer/message" "github.com/ChainSafe/chainbridge-core/types" + "github.com/ethereum/go-ethereum/accounts/abi" ) const ( PermissionlessGenericTransfer message.TransferType = "PermissionlessGenericTransfer" + ERC1155Transfer message.TransferType = "Erc1155" ) // GenericDepositHandler converts data pulled from generic deposit event logs into message @@ -79,3 +81,55 @@ func Erc20DepositHandler(sourceID, destId uint8, nonce uint64, resourceID types. return message.NewMessage(sourceID, destId, nonce, resourceID, message.FungibleTransfer, payload, message.Metadata{}), nil } + +func GetErc1155Type() (abi.Arguments, error) { + tokenIDsType, err := abi.NewType("uint256[]", "", nil) + if err != nil { + return nil, err + } + + amountsType, err := abi.NewType("uint256[]", "", nil) + if err != nil { + return nil, err + } + + recipientType, err := abi.NewType("bytes", "", nil) + if err != nil { + return nil, err + } + + transferDataType, err := abi.NewType("bytes", "", nil) + if err != nil { + return nil, err + } + + // Define the arguments using the created types + return abi.Arguments{ + abi.Argument{Name: "tokenIDs", Type: tokenIDsType, Indexed: false}, + abi.Argument{Name: "amounts", Type: amountsType, Indexed: false}, + abi.Argument{Name: "recipient", Type: recipientType, Indexed: false}, + abi.Argument{Name: "transferData", Type: transferDataType, Indexed: false}, + }, nil +} + +func Erc1155DepositHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { + + erc1155Type, err := GetErc1155Type() + if err != nil { + return nil, err + } + + decodedCallData, err := erc1155Type.UnpackValues(calldata) + if err != nil { + return nil, err + } + + payload := []interface{}{ + decodedCallData[0], + decodedCallData[1], + decodedCallData[2], + decodedCallData[3], + } + + return message.NewMessage(sourceID, destId, nonce, resourceID, ERC1155Transfer, payload, message.Metadata{}), nil +} diff --git a/chains/evm/listener/deposit-handler_test.go b/chains/evm/listener/deposit-handler_test.go index 3d221060..d88417fa 100644 --- a/chains/evm/listener/deposit-handler_test.go +++ b/chains/evm/listener/deposit-handler_test.go @@ -224,3 +224,68 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEventAlternativeAmount() { s.Equal(message, expected) s.Equal(big.NewInt(200), new(big.Int).SetBytes(message.Payload[0].([]byte))) } + +type Erc1155HandlerTestSuite struct { + suite.Suite +} + +func TestRunErc1155HandlerTestSuite(t *testing.T) { + suite.Run(t, new(Erc1155HandlerTestSuite)) +} + +func (s *Erc1155HandlerTestSuite) Test_Erc1155HandleEvent() { + callData := []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, 128, 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, 192, 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, 1, 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, 1, 64, 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, 1, 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, 2, 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, 1, 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, 3, 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, 20, 28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + depositLog := &events.Deposit{ + DestinationDomainID: 2, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: callData, + HandlerResponse: []byte{}, + } + sourceID := uint8(1) + + expected := &message.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: listener.ERC1155Transfer, + Payload: []interface{}{ + []*big.Int{ + big.NewInt(2), + }, + []*big.Int{ + big.NewInt(3), + }, + []byte{28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141}, + []byte{}, + }, + } + + message, err := listener.Erc1155DepositHandler(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *Erc1155HandlerTestSuite) Test_Erc1155HandleEvent_ErrInvalidCallData() { + callData := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 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, 192, 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, 1, 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, 1, 64, 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, 1, 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, 2, 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, 1, 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, 3, 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, 20, 28, 58, 3, 208, 76, 2, 107, 31, 75, 66, 8, 210, 206, 5, 60, 86, 134, 230, 251, 141, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + depositLog := &events.Deposit{ + DestinationDomainID: 2, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: callData, + HandlerResponse: []byte{}, + } + sourceID := uint8(1) + + message, err := listener.Erc1155DepositHandler(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(message) + s.NotNil(err) +} diff --git a/e2e/evm/evm_test.go b/e2e/evm/evm_test.go index bc38a2c6..658497ee 100644 --- a/e2e/evm/evm_test.go +++ b/e2e/evm/evm_test.go @@ -32,6 +32,7 @@ import ( "github.com/ChainSafe/chainbridge-core/keystore" "github.com/ChainSafe/sygma-relayer/chains/evm/calls/contracts/bridge" + "github.com/ChainSafe/sygma-relayer/chains/evm/calls/contracts/erc1155" "github.com/ChainSafe/sygma-relayer/e2e/evm" ) @@ -54,30 +55,32 @@ func Test_EVM2EVM(t *testing.T) { config := evm.BridgeConfig{ BridgeAddr: common.HexToAddress("0x6CdE2Cd82a4F8B74693Ff5e194c19CA08c2d1c68"), - Erc20Addr: common.HexToAddress("0x37356a2B2EbF65e5Ea18BD93DeA6869769099739"), + Erc20Addr: common.HexToAddress("0x78E5b9cEC9aEA29071f070C8cC561F692B3511A6"), Erc20HandlerAddr: common.HexToAddress("0x02091EefF969b33A5CE8A729DaE325879bf76f90"), Erc20ResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{0}, 31)), - Erc20LockReleaseAddr: common.HexToAddress("0x78E5b9cEC9aEA29071f070C8cC561F692B3511A6"), + Erc20LockReleaseAddr: common.HexToAddress("0x1ED1d77911944622FCcDDEad8A731fd77E94173e"), Erc20LockReleaseHandlerAddr: common.HexToAddress("0x02091EefF969b33A5CE8A729DaE325879bf76f90"), Erc20LockReleaseResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{3}, 31)), - Erc721Addr: common.HexToAddress("0xE54Dc792c226AEF99D6086527b98b36a4ADDe56a"), + Erc721Addr: common.HexToAddress("0xd3Eb00fCE476aEFdC76A02F3531b7A0C6D5238B3"), Erc721HandlerAddr: common.HexToAddress("0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760"), Erc721ResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{2}, 31)), - GenericHandlerAddr: common.HexToAddress("0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66"), + GenericHandlerAddr: common.HexToAddress("0xa4640d1315Be1f88aC4F81546AA2C785cf247C31"), GenericResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{1}, 31)), - AssetStoreAddr: common.HexToAddress("0xB1387B365AE7294Ea13bad9db83436e671DD16Ba"), + AssetStoreAddr: common.HexToAddress("0x979C2e7347c9831E18870aB886f0101EBC771CeB"), - PermissionlessGenericHandlerAddr: common.HexToAddress("0xE837D42dd3c685839a418886f418769BDD23546b"), + PermissionlessGenericHandlerAddr: common.HexToAddress("0xa2451c8553371E754F5e93A440aDcCa1c0DcF395"), PermissionlessGenericResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{5}, 31)), - BasicFeeHandlerAddr: common.HexToAddress("0x8dA96a8C2b2d3e5ae7e668d0C94393aa8D5D3B94"), - FeeHandlerWithOracleAddr: common.HexToAddress("0x30d704A60037DfE54e7e4D242Ea0cBC6125aE497"), - FeeRouterAddress: common.HexToAddress("0x1CcB4231f2ff299E1E049De76F0a1D2B415C563A"), - BasicFee: evm.BasicFee, - OracleFee: evm.OracleFee, + Erc1155Addr: common.HexToAddress("0x5e6924e6A120bd833617D0873f0a1b747ee2D743"), + Erc1155HandlerAddr: common.HexToAddress("0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED"), + Erc1155ResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{4}, 31)), + + BasicFeeHandlerAddr: common.HexToAddress("0x1CcB4231f2ff299E1E049De76F0a1D2B415C563A"), + FeeRouterAddress: common.HexToAddress("0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66"), + BasicFee: evm.BasicFee, } pk, _ := secp256k1.NewKeypairFromString("cc2c32b154490f09f70c1c8d4b997238448d649e0777495863db231c4ced3616") @@ -161,10 +164,6 @@ func (s *IntegrationTestSuite) SetupSuite() { if err != nil { panic(err) } - _, err = erc20Contract.ApproveTokens(s.config1.FeeHandlerWithOracleAddr, amountToApprove, transactor.TransactOptions{}) - if err != nil { - panic(err) - } erc20LRContract := erc20.NewERC20Contract(s.client1, s.config1.Erc20LockReleaseAddr, transactor1) _, err = erc20LRContract.MintTokens(mintTo, amountToMint, transactor.TransactOptions{}) @@ -203,22 +202,16 @@ func (s *IntegrationTestSuite) Test_Erc20Deposit() { destBalanceBefore, err := erc20Contract2.GetBalance(dstAddr) s.Nil(err) - var feeOracleSignature = "8167ba25cf7a08a43aae68576b71f0e42b6281a379a245a8be016c5b16d6227d3941da8f50c7b99763493d6e6f4f36e290ecd9bacca927a2f1b5f157cbe67b171b" - var feeDataHash = "00000000000000000000000000000000000000000000000000011f667bbfc00000000000000000000000000000000000000000000000000006bb5a99744a9000000000000000000000000000000000000000000000000000000000174876e80000000000000000000000000000000000000000000000000000000000698d283a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - var feeData = evm.ConstructFeeData(feeOracleSignature, feeDataHash, amountToDeposit) - - depositTxHash, err := bridgeContract1.Erc20Deposit(dstAddr.Bytes(), amountToDeposit, s.config1.Erc20ResourceID, 2, feeData, + depositTxHash, err := bridgeContract1.Erc20Deposit(dstAddr.Bytes(), amountToDeposit, s.config1.Erc20ResourceID, 2, nil, transactor.TransactOptions{ - Priority: uint8(2), // fast + Value: s.config1.BasicFee, }) s.Nil(err) log.Debug().Msgf("deposit hash %s", depositTxHash.Hex()) - depositTx, _, err := s.client1.TransactionByHash(context.Background(), *depositTxHash) + _, _, err = s.client1.TransactionByHash(context.Background(), *depositTxHash) s.Nil(err) - // check gas price of deposit tx - 140 gwei - s.Equal(big.NewInt(140000000000), depositTx.GasPrice()) err = evm.WaitForProposalExecuted(s.client2, s.config2.BridgeAddr) s.Nil(err) @@ -237,9 +230,7 @@ func (s *IntegrationTestSuite) Test_Erc721Deposit() { tokenId := big.NewInt(int64(rand.Int())) metadata := "metadata.url" - txOptions := transactor.TransactOptions{ - Priority: uint8(2), // fast - } + txOptions := transactor.TransactOptions{} dstAddr := keystore.TestKeyRing.EthereumKeys[keystore.BobKey].CommonAddress() @@ -275,10 +266,8 @@ func (s *IntegrationTestSuite) Test_Erc721Deposit() { ) s.Nil(err) - depositTx, _, err := s.client1.TransactionByHash(context.Background(), *depositTxHash) + _, _, err = s.client1.TransactionByHash(context.Background(), *depositTxHash) s.Nil(err) - // check gas price of deposit tx - 50 gwei (slow) - s.Equal(big.NewInt(50000000000), depositTx.GasPrice()) err = evm.WaitForProposalExecuted(s.client2, s.config2.BridgeAddr) s.Nil(err) @@ -310,10 +299,8 @@ func (s *IntegrationTestSuite) Test_GenericDeposit() { }) s.Nil(err) - depositTx, _, err := s.client1.TransactionByHash(context.Background(), *depositTxHash) + _, _, err = s.client1.TransactionByHash(context.Background(), *depositTxHash) s.Nil(err) - // check gas price of deposit tx - 140 gwei - s.Equal(big.NewInt(50000000000), depositTx.GasPrice()) err = evm.WaitForProposalExecuted(s.client2, s.config2.BridgeAddr) s.Nil(err) @@ -337,7 +324,7 @@ func (s *IntegrationTestSuite) Test_PermissionlessGenericDeposit() { hash, _ := substrateTypes.GetHash(substrateTypes.NewI64(int64(rand.Int()))) functionSig := string(crypto.Keccak256([]byte("storeWithDepositor(address,bytes32,address)"))[:4]) contractAddress := assetStoreContract2.ContractAddress() - maxFee := big.NewInt(200000) + maxFee := big.NewInt(600000) depositor := s.client1.From() var metadata []byte metadata = append(metadata, common.LeftPadBytes(hash[:], 32)...) @@ -371,8 +358,7 @@ func (s *IntegrationTestSuite) Test_RetryDeposit() { depositTxHash, err := bridgeContract1.Erc20Deposit(dstAddr.Bytes(), amountToDeposit, s.config1.Erc20LockReleaseResourceID, 2, nil, transactor.TransactOptions{ - Priority: uint8(2), // fast - Value: s.config1.BasicFee, + Value: s.config1.BasicFee, }) s.Nil(err) @@ -382,16 +368,12 @@ func (s *IntegrationTestSuite) Test_RetryDeposit() { s.Nil(err) time.Sleep(time.Second * 15) - _, err = erc20Contract2.MintTokens(s.config2.Erc20HandlerAddr, amountToMint, transactor.TransactOptions{ - Priority: uint8(2), // fast - }) + _, err = erc20Contract2.MintTokens(s.config2.Erc20HandlerAddr, amountToMint, transactor.TransactOptions{}) if err != nil { return } - retryTxHash, err := bridgeContract1.Retry(*depositTxHash, transactor.TransactOptions{ - Priority: uint8(2), // fast - }) + retryTxHash, err := bridgeContract1.Retry(*depositTxHash, transactor.TransactOptions{}) if err != nil { return } @@ -417,18 +399,14 @@ func (s *IntegrationTestSuite) Test_MultipleDeposits() { destBalanceBefore, err := erc20Contract2.GetBalance(dstAddr) s.Nil(err) - var feeOracleSignature = "8167ba25cf7a08a43aae68576b71f0e42b6281a379a245a8be016c5b16d6227d3941da8f50c7b99763493d6e6f4f36e290ecd9bacca927a2f1b5f157cbe67b171b" - var feeDataHash = "00000000000000000000000000000000000000000000000000011f667bbfc00000000000000000000000000000000000000000000000000006bb5a99744a9000000000000000000000000000000000000000000000000000000000174876e80000000000000000000000000000000000000000000000000000000000698d283a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - var feeData = evm.ConstructFeeData(feeOracleSignature, feeDataHash, amountToDeposit) - numOfDeposits := 25 var wg sync.WaitGroup for i := 0; i < numOfDeposits; i++ { go func() { - _, err := bridgeContract1.Erc20Deposit(dstAddr.Bytes(), amountToDeposit, s.config1.Erc20ResourceID, 2, feeData, + _, err := bridgeContract1.Erc20Deposit(dstAddr.Bytes(), amountToDeposit, s.config1.Erc20ResourceID, 2, nil, transactor.TransactOptions{ - Priority: uint8(2), // fast + Value: s.config1.BasicFee, }) wg.Add(1) defer wg.Done() @@ -446,3 +424,57 @@ func (s *IntegrationTestSuite) Test_MultipleDeposits() { //Balance has increased s.Equal(1, destBalanceAfter.Cmp(destBalanceBefore)) } + +func (s *IntegrationTestSuite) Test_Erc1155Deposit() { + tokenId := big.NewInt(int64(rand.Int())) + amount := big.NewInt(int64(rand.Int())) + + metadata := "metadata.url" + + txOptions := transactor.TransactOptions{} + + dstAddr := keystore.TestKeyRing.EthereumKeys[keystore.BobKey].CommonAddress() + + // 1155 contract for evm1 + transactor1 := signAndSend.NewSignAndSendTransactor(s.fabric1, s.gasPricer1, s.client1) + erc1155Contract1 := erc1155.NewErc1155Contract(s.client1, s.config1.Erc1155Addr, transactor1) + bridgeContract1 := bridge.NewBridgeContract(s.client1, s.config1.BridgeAddr, transactor1) + + // 1155 contract for evm2 + transactor2 := signAndSend.NewSignAndSendTransactor(s.fabric2, s.gasPricer2, s.client2) + erc1155Contract2 := erc1155.NewErc1155Contract(s.client2, s.config2.Erc1155Addr, transactor2) + + // Mint token and give approval + // This is done here so token only exists on evm1 + _, err := erc1155Contract1.Mint(tokenId, amount, []byte{0}, s.client1.From(), txOptions) + s.Nil(err, "Mint failed") + _, err = erc1155Contract1.Approve(tokenId, s.config1.Erc1155HandlerAddr, txOptions) + s.Nil(err, "Approve failed") + + initialAmount, err := erc1155Contract1.BalanceOf(s.client1.From(), tokenId) + s.Nil(err) + s.Equal(0, initialAmount.Cmp(amount)) + + depositTxHash, err := bridgeContract1.Erc1155Deposit( + tokenId, amount, metadata, dstAddr, s.config1.Erc1155ResourceID, 2, nil, transactor.TransactOptions{ + Value: s.config1.BasicFee, + }, + ) + s.Nil(err) + + _, _, err = s.client1.TransactionByHash(context.Background(), *depositTxHash) + s.Nil(err) + + err = evm.WaitForProposalExecuted(s.client2, s.config2.BridgeAddr) + s.Nil(err) + + // Check on evm1 that token is burned + sourceAmount, err := erc1155Contract1.BalanceOf(s.client1.From(), tokenId) + s.Nil(err) + s.Equal(0, sourceAmount.Cmp(big.NewInt(0))) + + // Check on evm2 that token is minted to destination address + dstAmount, err := erc1155Contract2.BalanceOf(dstAddr, tokenId) + s.Nil(err) + s.Equal(0, dstAmount.Cmp(initialAmount)) +} diff --git a/e2e/evm/util.go b/e2e/evm/util.go index a49cc189..1824299b 100644 --- a/e2e/evm/util.go +++ b/e2e/evm/util.go @@ -5,7 +5,6 @@ package evm import ( "context" - "encoding/hex" "errors" "math/big" "time" @@ -21,10 +20,9 @@ import ( ) var TestTimeout = time.Minute * 4 -var BasicFee = big.NewInt(1000000000000000) +var BasicFee = big.NewInt(100000000000000) var OracleFee = uint16(500) // 5% - multiplied by 100 to not lose precision on contract side var GasUsed = uint32(2000000000) -var FeeOracleAddress = common.HexToAddress("0x70B7D7448982b15295150575541D1d3b862f7FE9") type Client interface { LatestBlock() (*big.Int, error) @@ -60,11 +58,17 @@ type BridgeConfig struct { Erc721HandlerAddr common.Address Erc721ResourceID types.ResourceID + Erc1155Addr common.Address + Erc1155HandlerAddr common.Address + Erc1155ResourceID types.ResourceID + BasicFeeHandlerAddr common.Address FeeRouterAddress common.Address FeeHandlerWithOracleAddr common.Address BasicFee *big.Int - OracleFee uint16 + + MaxGasPrice *big.Int + GasMultiplier *big.Float } func WaitForProposalExecuted(client Client, bridge common.Address) error { @@ -98,12 +102,3 @@ func WaitForProposalExecuted(client Client, bridge common.Address) error { } } } - -func ConstructFeeData(feeOracleSignature string, feeDataHash string, amountToDeposit *big.Int) []byte { - decodedFeeOracleSignature, _ := hex.DecodeString(feeOracleSignature) - decodedFeeData, _ := hex.DecodeString(feeDataHash) - amountToDepositBytes := calls.SliceTo32Bytes(common.LeftPadBytes(amountToDeposit.Bytes(), 32)) - feeData := append(decodedFeeData, decodedFeeOracleSignature...) - feeData = append(feeData, amountToDepositBytes[:]...) - return feeData -} diff --git a/e2e/substrate/substrate_test.go b/e2e/substrate/substrate_test.go index fefa8c43..f23bc083 100644 --- a/e2e/substrate/substrate_test.go +++ b/e2e/substrate/substrate_test.go @@ -51,19 +51,17 @@ func Test_EVMSubstrate(t *testing.T) { evmConfig := evm.BridgeConfig{ BridgeAddr: common.HexToAddress("0x6CdE2Cd82a4F8B74693Ff5e194c19CA08c2d1c68"), - Erc20Addr: common.HexToAddress("0x37356a2B2EbF65e5Ea18BD93DeA6869769099739"), + Erc20Addr: common.HexToAddress("0x78E5b9cEC9aEA29071f070C8cC561F692B3511A6"), Erc20HandlerAddr: common.HexToAddress("0x02091EefF969b33A5CE8A729DaE325879bf76f90"), Erc20ResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{0}, 31)), - Erc20LockReleaseAddr: common.HexToAddress("0x78E5b9cEC9aEA29071f070C8cC561F692B3511A6"), + Erc20LockReleaseAddr: common.HexToAddress("0x1ED1d77911944622FCcDDEad8A731fd77E94173e"), Erc20LockReleaseHandlerAddr: common.HexToAddress("0x02091EefF969b33A5CE8A729DaE325879bf76f90"), Erc20LockReleaseResourceID: calls.SliceTo32Bytes(common.LeftPadBytes([]byte{3}, 31)), - BasicFeeHandlerAddr: common.HexToAddress("0x8dA96a8C2b2d3e5ae7e668d0C94393aa8D5D3B94"), - FeeHandlerWithOracleAddr: common.HexToAddress("0x30d704A60037DfE54e7e4D242Ea0cBC6125aE497"), - FeeRouterAddress: common.HexToAddress("0x1CcB4231f2ff299E1E049De76F0a1D2B415C563A"), - BasicFee: evm.BasicFee, - OracleFee: evm.OracleFee, + BasicFeeHandlerAddr: common.HexToAddress("0x1CcB4231f2ff299E1E049De76F0a1D2B415C563A"), + FeeRouterAddress: common.HexToAddress("0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66"), + BasicFee: evm.BasicFee, } pk, _ := secp256k1.NewKeypairFromString("cc2c32b154490f09f70c1c8d4b997238448d649e0777495863db231c4ced3616") diff --git a/e2e/substrate/util.go b/e2e/substrate/util.go index 79205a46..c9dcb058 100644 --- a/e2e/substrate/util.go +++ b/e2e/substrate/util.go @@ -26,10 +26,9 @@ import ( ) var TestTimeout = time.Minute * 4 -var BasicFee = big.NewInt(1000000000000000) +var BasicFee = big.NewInt(100000000000000) var OracleFee = uint16(500) // 5% - multiplied by 100 to not lose precision on contract side var GasUsed = uint32(2000000000) -var FeeOracleAddress = common.HexToAddress("0x70B7D7448982b15295150575541D1d3b862f7FE9") var SubstratePK = signature.KeyringPair{ URI: "//Alice", PublicKey: []byte{0xd4, 0x35, 0x93, 0xc7, 0x15, 0xfd, 0xd3, 0x1c, 0x61, 0x14, 0x1a, 0xbd, 0x4, 0xa9, 0x9f, 0xd6, 0x82, 0x2c, 0x85, 0x58, 0x85, 0x4c, 0xcd, 0xe3, 0x9a, 0x56, 0x84, 0xe7, 0xa5, 0x6d, 0xa2, 0x7d}, diff --git a/example/app/app.go b/example/app/app.go index f61316f1..37212f29 100644 --- a/example/app/app.go +++ b/example/app/app.go @@ -172,6 +172,11 @@ func Run() error { depositHandler.RegisterDepositHandler(handler.Address, coreListener.Erc721DepositHandler) mh.RegisterMessageHandler(handler.Address, coreExecutor.ERC721MessageHandler) } + case "erc1155": + { + depositHandler.RegisterDepositHandler(handler.Address, listener.Erc1155DepositHandler) + mh.RegisterMessageHandler(handler.Address, executor.Erc1155MessageHandler) + } } } depositListener := coreEvents.NewListener(client) diff --git a/example/cfg/config_evm-evm_1.json b/example/cfg/config_evm-evm_1.json index 221943e6..e86b4276 100644 --- a/example/cfg/config_evm-evm_1.json +++ b/example/cfg/config_evm-evm_1.json @@ -29,13 +29,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, @@ -58,13 +62,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, diff --git a/example/cfg/config_evm-evm_2.json b/example/cfg/config_evm-evm_2.json index 38188f7a..ee7e538a 100644 --- a/example/cfg/config_evm-evm_2.json +++ b/example/cfg/config_evm-evm_2.json @@ -29,13 +29,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, @@ -58,13 +62,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, diff --git a/example/cfg/config_evm-evm_3.json b/example/cfg/config_evm-evm_3.json index 60835a21..61d55218 100644 --- a/example/cfg/config_evm-evm_3.json +++ b/example/cfg/config_evm-evm_3.json @@ -29,13 +29,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, @@ -58,13 +62,17 @@ "type": "erc721", "address": "0xC2D334e2f27A9dB2Ed8C4561De86C1A00EBf6760" }, + { + "type": "erc1155", + "address": "0x156fA85e1df5d69B0F138dcEbAa5a14ca640FaED" + }, { "type": "permissionedGeneric", - "address": "0xF28c11CB14C6d2B806f99EA8b138F65e74a1Ed66" + "address": "0xa4640d1315Be1f88aC4F81546AA2C785cf247C31" }, { "type": "permissionlessGeneric", - "address": "0xE837D42dd3c685839a418886f418769BDD23546b" + "address": "0xa2451c8553371E754F5e93A440aDcCa1c0DcF395" } ], "gasLimit": 9000000, diff --git a/example/docker-compose.yml b/example/docker-compose.yml index 44891b15..768774a3 100644 --- a/example/docker-compose.yml +++ b/example/docker-compose.yml @@ -4,7 +4,7 @@ version: '3' services: evm1-1: - image: ghcr.io/sygmaprotocol/sygma-solidity:evm1-v2.3.0 + image: ghcr.io/sygmaprotocol/sygma-solidity:evm1-v2.5.3 container_name: evm1-1 command: ganache-cli --chainId 1337 -d --db data/ --blockTime 2 > /dev/null logging: @@ -14,7 +14,7 @@ services: # SECOND CHAIN evm2-1: - image: ghcr.io/sygmaprotocol/sygma-solidity:evm2-v2.3.0 + image: ghcr.io/sygmaprotocol/sygma-solidity:evm2-v2.5.3 command: ganache-cli --chainId 1338 -d --db data/ --blockTime 2 > /dev/null container_name: evm2-1 logging: @@ -68,23 +68,6 @@ services: - ./cfg:/cfg restart: always - fee-oracle: - container_name: fee-oracle - image: "ghcr.io/sygmaprotocol/sygma-fee-oracle:v1.1.1" - command: go run main.go server -c ./fee-oracle-config/config.yaml -d ./fee-oracle-config/domain.json - depends_on: - - evm1-1 - - substrate-pallet - volumes: - - ./fee-oracle-config:/app/feeOracle/fee-oracle-config - ports: - - "8091:8091" - environment: - - APP_MODE=debug - - IDENTITY_KEY=71aec985a12cfcbabc7969845215ceac56038e87477c8337e373eab7b15796cf - - IDENTITY_KEY_TYPE=secp256k1 - - otel-collector: container_name: otel-collector image: otel/opentelemetry-collector