Skip to content

Commit

Permalink
Ensure that the same child token addresses are calculated on both cha…
Browse files Browse the repository at this point in the history
…ins (#1621)

* Provide correct addresses for child token templates to predicates

* Assert that rootTokenToChildToken exists in the provided predicate ABI
  • Loading branch information
Stefan-Ethernal committed Jun 26, 2023
1 parent b624822 commit 8f39a41
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 58 deletions.
18 changes: 9 additions & 9 deletions command/rootchain/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ var (
rootchainConfig.RootNativeERC20Address = addr
},
erc20TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.ERC20TemplateAddress = addr
rootchainConfig.ChildERC20Address = addr
},
rootERC721PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.RootERC721PredicateAddress = addr
Expand All @@ -89,7 +89,7 @@ var (
rootchainConfig.ChildMintableERC721PredicateAddress = addr
},
erc721TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.ERC721TemplateAddress = addr
rootchainConfig.ChildERC721Address = addr
},
rootERC1155PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.RootERC1155PredicateAddress = addr
Expand All @@ -98,7 +98,7 @@ var (
rootchainConfig.ChildMintableERC1155PredicateAddress = addr
},
erc1155TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.ERC1155TemplateAddress = addr
rootchainConfig.ChildERC1155Address = addr
},
customSupernetManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.CustomSupernetManagerAddress = addr
Expand Down Expand Up @@ -149,7 +149,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewChildERC20Predicate: contracts.ChildERC20PredicateContract,
NewChildTokenTemplate: config.ERC20TemplateAddress,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NativeTokenRootAddress: nativeTokenRootAddr,
}

Expand All @@ -164,7 +164,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewRootERC20Predicate: contracts.RootMintableERC20PredicateContract,
NewChildTokenTemplate: config.ERC20TemplateAddress,
NewChildTokenTemplate: config.ChildERC20Address,
}

return initContract(fmt, relayer, initParams,
Expand All @@ -178,7 +178,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewChildERC721Predicate: contracts.ChildERC721PredicateContract,
NewChildTokenTemplate: config.ERC721TemplateAddress,
NewChildTokenTemplate: contracts.ChildERC721Contract,
}

return initContract(fmt, relayer, initParams,
Expand All @@ -192,7 +192,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewRootERC721Predicate: contracts.RootMintableERC721PredicateContract,
NewChildTokenTemplate: config.ERC721TemplateAddress,
NewChildTokenTemplate: config.ChildERC721Address,
}

return initContract(fmt, relayer, initParams,
Expand All @@ -206,7 +206,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewChildERC1155Predicate: contracts.ChildERC1155PredicateContract,
NewChildTokenTemplate: config.ERC1155TemplateAddress,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
}

return initContract(fmt, relayer, initParams,
Expand All @@ -220,7 +220,7 @@ var (
NewStateSender: config.StateSenderAddress,
NewExitHelper: config.ExitHelperAddress,
NewRootERC1155Predicate: contracts.RootMintableERC1155PredicateContract,
NewChildTokenTemplate: config.ERC1155TemplateAddress,
NewChildTokenTemplate: config.ChildERC1155Address,
}

return initContract(fmt, relayer, initParams,
Expand Down
12 changes: 6 additions & 6 deletions consensus/polybft/contracts_initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func getInitERC20PredicateInput(config *BridgeConfig, childChainMintable bool) (
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC20Predicate: config.ChildMintableERC20PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewChildTokenTemplate: config.ChildERC20Addr,
}
} else {
params = &contractsapi.InitializeChildERC20PredicateFn{
Expand All @@ -92,7 +92,7 @@ func getInitERC20PredicateACLInput(config *BridgeConfig, owner types.Address,
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC20Predicate: config.ChildMintableERC20PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewChildTokenTemplate: config.ChildERC20Addr,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
Expand Down Expand Up @@ -121,7 +121,7 @@ func getInitERC721PredicateInput(config *BridgeConfig, childOriginatedTokens boo
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC721Predicate: config.ChildMintableERC721PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewChildTokenTemplate: config.ChildERC721Addr,
}
} else {
params = &contractsapi.InitializeChildERC721PredicateFn{
Expand All @@ -145,7 +145,7 @@ func getInitERC721PredicateACLInput(config *BridgeConfig, owner types.Address,
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC721Predicate: config.ChildMintableERC721PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC721Contract,
NewChildTokenTemplate: config.ChildERC721Addr,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
Expand Down Expand Up @@ -173,7 +173,7 @@ func getInitERC1155PredicateInput(config *BridgeConfig, childChainMintable bool)
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC1155Predicate: config.ChildMintableERC1155PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
NewChildTokenTemplate: config.ChildERC1155Addr,
}
} else {
params = &contractsapi.InitializeChildERC1155PredicateFn{
Expand All @@ -197,7 +197,7 @@ func getInitERC1155PredicateACLInput(config *BridgeConfig, owner types.Address,
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC1155Predicate: config.ChildMintableERC1155PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
NewChildTokenTemplate: config.ChildERC1155Addr,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
Expand Down
2 changes: 1 addition & 1 deletion consensus/polybft/contractsapi/gen_sc_data.go

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions consensus/polybft/polybft_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ type BridgeConfig struct {
ChildMintableERC721PredicateAddr types.Address `json:"erc721ChildMintablePredicateAddress"`
RootERC1155PredicateAddr types.Address `json:"erc1155PredicateAddress"`
ChildMintableERC1155PredicateAddr types.Address `json:"erc1155ChildMintablePredicateAddress"`
ChildERC20Addr types.Address `json:"childERC20Address"`
ChildERC721Addr types.Address `json:"childERC721Address"`
ChildERC1155Addr types.Address `json:"childERC1155Address"`
CustomSupernetManagerAddr types.Address `json:"customSupernetManagerAddr"`
StakeManagerAddr types.Address `json:"stakeManagerAddr"`
// only populated if stake-manager-deploy command is executed, and used for e2e tests
Expand Down Expand Up @@ -125,13 +128,13 @@ type RootchainConfig struct {
RootERC20PredicateAddress types.Address
ChildMintableERC20PredicateAddress types.Address
RootNativeERC20Address types.Address
ERC20TemplateAddress types.Address
ChildERC20Address types.Address
RootERC721PredicateAddress types.Address
ChildMintableERC721PredicateAddress types.Address
ERC721TemplateAddress types.Address
ChildERC721Address types.Address
RootERC1155PredicateAddress types.Address
ChildMintableERC1155PredicateAddress types.Address
ERC1155TemplateAddress types.Address
ChildERC1155Address types.Address
CustomSupernetManagerAddress types.Address
StakeManagerAddress types.Address
StakeTokenAddress types.Address
Expand All @@ -152,6 +155,9 @@ func (r *RootchainConfig) ToBridgeConfig() *BridgeConfig {
ChildMintableERC721PredicateAddr: r.ChildMintableERC721PredicateAddress,
RootERC1155PredicateAddr: r.RootERC1155PredicateAddress,
ChildMintableERC1155PredicateAddr: r.ChildMintableERC1155PredicateAddress,
ChildERC20Addr: r.ChildERC20Address,
ChildERC721Addr: r.ChildERC721Address,
ChildERC1155Addr: r.ChildERC1155Address,
CustomSupernetManagerAddr: r.CustomSupernetManagerAddress,
StakeManagerAddr: r.StakeManagerAddress,
BLSAddress: r.BLSAddress,
Expand Down
87 changes: 48 additions & 39 deletions e2e-polybft/e2e/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,18 +388,18 @@ func TestE2E_Bridge_ERC721Transfer(t *testing.T) {
// MAP_TOKEN_SIG and DEPOSIT_BATCH_SIG state sync events
checkStateSyncResultLogs(t, logs, 2)

// retrieve child token address
rootToChildTokenFn := contractsapi.ChildERC721Predicate.Abi.Methods["rootTokenToChildToken"]
input, err := rootToChildTokenFn.Encode([]interface{}{rootERC721Addr})
require.NoError(t, err)
// retrieve child token address (from both chains, and assert they are the same)
l1ChildTokenAddr := getChildToken(t, contractsapi.RootERC721Predicate.Abi, polybftCfg.Bridge.RootERC721PredicateAddr,
types.Address(rootERC721Addr), rootchainTxRelayer)
l2ChildTokenAddr := getChildToken(t, contractsapi.ChildERC721Predicate.Abi, contracts.ChildERC721PredicateContract,
types.Address(rootERC721Addr), txRelayer)

childTokenRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.ChildERC721PredicateContract), input)
require.NoError(t, err)

childTokenAddr := types.StringToAddress(childTokenRaw)
t.Log("L1 child token", l1ChildTokenAddr)
t.Log("L2 child token", l2ChildTokenAddr)
require.Equal(t, l1ChildTokenAddr, l2ChildTokenAddr)

for i, receiver := range receiversAddrs {
owner := erc721OwnerOf(t, big.NewInt(int64(i)), childTokenAddr, txRelayer)
owner := erc721OwnerOf(t, big.NewInt(int64(i)), l2ChildTokenAddr, txRelayer)
require.Equal(t, receiver, owner)
}

Expand All @@ -416,7 +416,7 @@ func TestE2E_Bridge_ERC721Transfer(t *testing.T) {
tokenIDs[i],
validatorSrv.JSONRPCAddr(),
contracts.ChildERC721PredicateContract,
childTokenAddr,
l2ChildTokenAddr,
false)
require.NoError(t, err)
}
Expand Down Expand Up @@ -544,15 +544,14 @@ func TestE2E_Bridge_ERC1155Transfer(t *testing.T) {
checkStateSyncResultLogs(t, logs, 2)

// retrieve child token address
rootToChildTokenFn := contractsapi.ChildERC1155Predicate.Abi.Methods["rootTokenToChildToken"]
input, err := rootToChildTokenFn.Encode([]interface{}{rootERC1155Addr})
require.NoError(t, err)
l1ChildTokenAddr := getChildToken(t, contractsapi.RootERC1155Predicate.Abi, polybftCfg.Bridge.RootERC1155PredicateAddr,
types.Address(rootERC1155Addr), rootchainTxRelayer)
l2ChildTokenAddr := getChildToken(t, contractsapi.ChildERC1155Predicate.Abi, contracts.ChildERC1155PredicateContract,
types.Address(rootERC1155Addr), txRelayer)

childTokenRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.ChildERC1155PredicateContract), input)
require.NoError(t, err)

childTokenAddr := types.StringToAddress(childTokenRaw)
t.Logf("Child token addr: %s\n", childTokenAddr)
t.Log("L1 child token", l1ChildTokenAddr)
t.Log("L2 child token", l2ChildTokenAddr)
require.Equal(t, l1ChildTokenAddr, l2ChildTokenAddr)

// check receivers balances got increased by deposited amount
for i, receiver := range receivers {
Expand All @@ -564,7 +563,7 @@ func TestE2E_Bridge_ERC1155Transfer(t *testing.T) {
balanceInput, err := balanceOfFn.EncodeAbi()
require.NoError(t, err)

balanceRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(childTokenAddr), balanceInput)
balanceRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(l2ChildTokenAddr), balanceInput)
require.NoError(t, err)

balance, err := types.ParseUint256orHex(&balanceRaw)
Expand All @@ -590,7 +589,7 @@ func TestE2E_Bridge_ERC1155Transfer(t *testing.T) {
tokenIDs[i],
validatorSrv.JSONRPCAddr(),
contracts.ChildERC1155PredicateContract,
childTokenAddr,
l2ChildTokenAddr,
false)
require.NoError(t, err)
}
Expand Down Expand Up @@ -701,11 +700,14 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
var mintableTokenMapped contractsapi.MintableTokenMappedEvent

t.Run("bridge native tokens", func(t *testing.T) {
// rootToken represents deposit token (basically native mintable token from the Supernets)
rootToken := contracts.NativeERC20TokenContract

// try sending a single native token deposit transaction
// it should fail, because depositors are not allow listed for bridge transactions
err = cluster.Bridge.Deposit(
common.ERC20,
contracts.NativeERC20TokenContract,
rootToken,
contracts.RootMintableERC20PredicateContract,
depositorKeys[0],
depositors[0].String(),
Expand All @@ -724,7 +726,7 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
// make sure deposit is successfully executed
err = cluster.Bridge.Deposit(
common.ERC20,
contracts.NativeERC20TokenContract,
rootToken,
contracts.RootMintableERC20PredicateContract,
key,
depositors[i].String(),
Expand Down Expand Up @@ -756,20 +758,23 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
rootchainLatestBlock, err := rootchainTxRelayer.Client().Eth().BlockNumber()
require.NoError(t, err)

// retrieve child mintable token address
// retrieve child mintable token address from both chains and make sure they are the same
l1ChildToken := getChildToken(t, contractsapi.ChildMintableERC20Predicate.Abi, polybftCfg.Bridge.ChildMintableERC20PredicateAddr,
rootToken, rootchainTxRelayer)
l2ChildToken := getChildToken(t, contractsapi.RootMintableERC20Predicate.Abi, contracts.RootMintableERC20PredicateContract,
rootToken, childchainTxRelayer)

t.Log("L1 child token", l1ChildToken)
t.Log("L2 child token", l2ChildToken)
require.Equal(t, l1ChildToken, l2ChildToken)

logs, err := getFilteredLogs(mintableTokenMapped.Sig(), 0, rootchainLatestBlock, rootchainTxRelayer.Client().Eth())
require.NoError(t, err)
require.Len(t, logs, 1)

ok, err := mintableTokenMapped.ParseLog(logs[0])
require.NoError(t, err)
require.True(t, ok)

t.Log("Child token address", mintableTokenMapped.ChildToken)

// check that balances on rootchain have increased by deposited amounts
for _, depositor := range depositors {
balance := erc20BalanceOf(t, depositor, mintableTokenMapped.ChildToken, rootchainTxRelayer)
balance := erc20BalanceOf(t, depositor, l1ChildToken, rootchainTxRelayer)
require.Equal(t, big.NewInt(amount), balance)
}

Expand All @@ -789,7 +794,7 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
"",
cluster.Bridge.JSONRPCAddr(),
polybftCfg.Bridge.ChildMintableERC20PredicateAddr,
mintableTokenMapped.ChildToken,
l1ChildToken,
true)
require.NoError(t, err)
}
Expand Down Expand Up @@ -896,20 +901,24 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
latestRootchainBlock, err := rootchainTxRelayer.Client().Eth().BlockNumber()
require.NoError(t, err)

// retrieve child token addresses on both chains and make sure they are the same
l1ChildToken := getChildToken(t, contractsapi.ChildMintableERC721Predicate.Abi, polybftCfg.Bridge.ChildMintableERC721PredicateAddr,
types.Address(rootERC721Token), rootchainTxRelayer)
l2ChildToken := getChildToken(t, contractsapi.RootMintableERC721Predicate.Abi, contracts.RootMintableERC721PredicateContract,
types.Address(rootERC721Token), childchainTxRelayer)

t.Log("L1 child token", l1ChildToken)
t.Log("L2 child token", l2ChildToken)
require.Equal(t, l1ChildToken, l2ChildToken)

logs, err := getFilteredLogs(mintableTokenMapped.Sig(), rootchainInitialBlock, latestRootchainBlock,
rootchainTxRelayer.Client().Eth())
require.NoError(t, err)
require.Len(t, logs, 1)

ok, err := mintableTokenMapped.ParseLog(logs[0])
require.NoError(t, err)
require.True(t, ok)

childERC721 := mintableTokenMapped.ChildToken

// check owner on the rootchain
for i := uint64(0); i < transfersCount; i++ {
owner := erc721OwnerOf(t, new(big.Int).SetUint64(i), childERC721, rootchainTxRelayer)
owner := erc721OwnerOf(t, new(big.Int).SetUint64(i), l1ChildToken, rootchainTxRelayer)
t.Log("ChildERC721 owner", owner)
require.Equal(t, depositors[i], owner)
}
Expand All @@ -924,7 +933,7 @@ func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) {
fmt.Sprintf("%d", i),
cluster.Bridge.JSONRPCAddr(),
polybftCfg.Bridge.ChildMintableERC721PredicateAddr,
childERC721,
l1ChildToken,
true)
require.NoError(t, err)
}
Expand Down
17 changes: 17 additions & 0 deletions e2e-polybft/e2e/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,20 @@ func queryNativeERC20Metadata(t *testing.T, funcName string, abiType *abi.Type,

return decodedResult["0"]
}

// getChildToken queries child token address for provided root token on the target predicate
func getChildToken(t *testing.T, predicateABI *abi.ABI, predicateAddr types.Address,
rootToken types.Address, relayer txrelayer.TxRelayer) types.Address {
t.Helper()

rootToChildTokenFn, exists := predicateABI.Methods["rootTokenToChildToken"]
require.True(t, exists, "rootTokenToChildToken function is not found in the provided predicate ABI definition")

input, err := rootToChildTokenFn.Encode([]interface{}{rootToken})
require.NoError(t, err)

childTokenRaw, err := relayer.Call(ethgo.ZeroAddress, ethgo.Address(predicateAddr), input)
require.NoError(t, err)

return types.StringToAddress(childTokenRaw)
}

0 comments on commit 8f39a41

Please sign in to comment.