Skip to content

Commit

Permalink
Introduce access list child chain mintable predicates (0xPolygon#1549)
Browse files Browse the repository at this point in the history
* Introduce ACL mintable predicates

* Deploy and initialize ACL miintable predicates

* Fix e2e tests
  • Loading branch information
Stefan-Ethernal authored May 29, 2023
1 parent cb00cd5 commit 550852d
Show file tree
Hide file tree
Showing 14 changed files with 580 additions and 170 deletions.
26 changes: 23 additions & 3 deletions command/genesis/polybft_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,23 +374,43 @@ func (p *genesisParams) deployContracts(totalStake *big.Int,
}

if len(params.bridgeAllowListAdmin) != 0 || len(params.bridgeBlockListAdmin) != 0 {
// rootchain originated tokens predicates (with access lists)
genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.ChildERC20PredicateAccessList,
artifact: contractsapi.ChildERC20PredicateACL,
address: contracts.ChildERC20PredicateContract,
})

genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.ChildERC721PredicateAccessList,
artifact: contractsapi.ChildERC721PredicateACL,
address: contracts.ChildERC721PredicateContract,
})

genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.ChildERC1155PredicateAccessList,
artifact: contractsapi.ChildERC1155PredicateACL,
address: contracts.ChildERC1155PredicateContract,
})

// childchain originated tokens predicates (with access lists)
genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.RootMintableERC20PredicateACL,
address: contracts.RootMintableERC20PredicateContract,
})

genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.RootMintableERC721PredicateACL,
address: contracts.RootMintableERC721PredicateContract,
})

genesisContracts = append(genesisContracts,
&contractInfo{
artifact: contractsapi.RootMintableERC1155PredicateACL,
address: contracts.RootMintableERC1155PredicateContract,
})
} else {
// rootchain originated tokens predicates
genesisContracts = append(genesisContracts,
Expand Down
144 changes: 96 additions & 48 deletions consensus/polybft/contracts_initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
"github.com/umbracle/ethgo/abi"
)

const (
contractCallGasLimit = 100_000_000
)

// getInitValidatorSetInput builds input parameters for ValidatorSet SC initialization
func getInitValidatorSetInput(polyBFTConfig PolyBFTConfig) ([]byte, error) {
initialValidators := make([]*contractsapi.ValidatorInit, len(polyBFTConfig.InitialValidatorSet))
Expand Down Expand Up @@ -45,9 +49,9 @@ func getInitRewardPoolInput(polybftConfig PolyBFTConfig) ([]byte, error) {
}

// getInitERC20PredicateInput builds initialization input parameters for child chain ERC20Predicate SC
func getInitERC20PredicateInput(config *BridgeConfig, childOriginatedTokens bool) ([]byte, error) {
func getInitERC20PredicateInput(config *BridgeConfig, childChainMintable bool) ([]byte, error) {
var params contractsapi.StateTransactionInput
if childOriginatedTokens {
if childChainMintable {
params = &contractsapi.InitializeRootMintableERC20PredicateFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
Expand All @@ -67,17 +71,31 @@ func getInitERC20PredicateInput(config *BridgeConfig, childOriginatedTokens bool
return params.EncodeAbi()
}

// getInitChildERC20PredicateAccessListInput builds input parameters for ChildERC20PredicateAccessList SC initialization
func getInitChildERC20PredicateAccessListInput(config *BridgeConfig, owner types.Address) ([]byte, error) {
params := &contractsapi.InitializeChildERC20PredicateAccessListFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC20Predicate: config.RootERC20PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewNativeTokenRootAddress: config.RootNativeERC20Addr,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
// getInitERC20PredicateACLInput builds initialization input parameters for child chain ERC20PredicateAccessList SC
func getInitERC20PredicateACLInput(config *BridgeConfig, owner types.Address,
childChainMintable bool) ([]byte, error) {
var params contractsapi.StateTransactionInput
if childChainMintable {
params = &contractsapi.InitializeRootMintableERC20PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC20Predicate: config.ChildMintableERC20PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
} else {
params = &contractsapi.InitializeChildERC20PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC20Predicate: config.RootERC20PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC20Contract,
NewNativeTokenRootAddress: config.RootNativeERC20Addr,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
}

return params.EncodeAbi()
Expand Down Expand Up @@ -105,26 +123,40 @@ func getInitERC721PredicateInput(config *BridgeConfig, childOriginatedTokens boo
return params.EncodeAbi()
}

// getInitChildERC721PredicateAccessListInput builds input parameters
// for ChildERC721PredicateAccessList SC initialization
func getInitChildERC721PredicateAccessListInput(config *BridgeConfig, owner types.Address) ([]byte, error) {
params := &contractsapi.InitializeChildERC721PredicateAccessListFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC721Predicate: config.RootERC721PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC721Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
// getInitERC721PredicateACLInput builds initialization input parameters
// for child chain ERC721PredicateAccessList SC
func getInitERC721PredicateACLInput(config *BridgeConfig, owner types.Address,
childChainMintable bool) ([]byte, error) {
var params contractsapi.StateTransactionInput
if childChainMintable {
params = &contractsapi.InitializeRootMintableERC721PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC721Predicate: config.ChildMintableERC721PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC721Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
} else {
params = &contractsapi.InitializeChildERC721PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC721Predicate: config.RootERC721PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC721Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
}

return params.EncodeAbi()
}

// getInitERC1155PredicateInput builds initialization input parameters for child chain ERC1155Predicate SC
func getInitERC1155PredicateInput(config *BridgeConfig, childOriginatedTokens bool) ([]byte, error) {
func getInitERC1155PredicateInput(config *BridgeConfig, childChainMintable bool) ([]byte, error) {
var params contractsapi.StateTransactionInput
if childOriginatedTokens {
if childChainMintable {
params = &contractsapi.InitializeRootMintableERC1155PredicateFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
Expand All @@ -143,17 +175,31 @@ func getInitERC1155PredicateInput(config *BridgeConfig, childOriginatedTokens bo
return params.EncodeAbi()
}

// getInitChildERC1155PredicateAccessListInput builds input parameters
// for ChildERC1155PredicateAccessList SC initialization
func getInitChildERC1155PredicateAccessListInput(config *BridgeConfig, owner types.Address) ([]byte, error) {
params := &contractsapi.InitializeChildERC1155PredicateAccessListFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC1155Predicate: config.RootERC1155PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
// getInitERC1155PredicateACLInput builds initialization input parameters
// for child chain ERC1155PredicateAccessList SC
func getInitERC1155PredicateACLInput(config *BridgeConfig, owner types.Address,
childChainMintable bool) ([]byte, error) {
var params contractsapi.StateTransactionInput
if childChainMintable {
params = &contractsapi.InitializeRootMintableERC1155PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewChildERC1155Predicate: config.ChildMintableERC1155PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
} else {
params = &contractsapi.InitializeChildERC1155PredicateACLFn{
NewL2StateSender: contracts.L2StateSenderContract,
NewStateReceiver: contracts.StateReceiverContract,
NewRootERC1155Predicate: config.RootERC1155PredicateAddr,
NewChildTokenTemplate: contracts.ChildERC1155Contract,
NewUseAllowList: owner != contracts.SystemCaller,
NewUseBlockList: owner != contracts.SystemCaller,
NewOwner: owner,
}
}

return params.EncodeAbi()
Expand All @@ -171,7 +217,7 @@ func mintRewardTokensToWalletAddress(polyBFTConfig *PolyBFTConfig, transition *s
return err
}

if err = initContract(polyBFTConfig.RewardConfig.WalletAddress,
if err = callContract(polyBFTConfig.RewardConfig.WalletAddress,
polyBFTConfig.RewardConfig.TokenAddress, input, "RewardToken", transition); err != nil {
return err
}
Expand All @@ -182,28 +228,30 @@ func mintRewardTokensToWalletAddress(polyBFTConfig *PolyBFTConfig, transition *s
return nil
}

mintFn := abi.MustNewMethod("function mint(address, uint256)")
mintFn := contractsapi.MintRootERC20Fn{
To: polyBFTConfig.RewardConfig.WalletAddress,
Amount: polyBFTConfig.RewardConfig.WalletAmount,
}

input, err = mintFn.Encode([]interface{}{polyBFTConfig.RewardConfig.WalletAddress,
polyBFTConfig.RewardConfig.WalletAmount})
input, err = mintFn.EncodeAbi()
if err != nil {
return err
}

return initContract(contracts.SystemCaller, polyBFTConfig.RewardConfig.TokenAddress, input, "RewardToken", transition)
return callContract(contracts.SystemCaller, polyBFTConfig.RewardConfig.TokenAddress, input, "RewardToken", transition)
}

func initContract(from, to types.Address, input []byte, contractName string, transition *state.Transition) error {
result := transition.Call2(from, to, input, big.NewInt(0), 100_000_000)
// callContract calls given smart contract function, encoded in input parameter
func callContract(from, to types.Address, input []byte, contractName string, transition *state.Transition) error {
result := transition.Call2(from, to, input, big.NewInt(0), contractCallGasLimit)
if result.Failed() {
if result.Reverted() {
unpackedRevert, err := abi.UnpackRevertError(result.ReturnValue)
if err == nil {
fmt.Printf("%v.initialize %v\n", contractName, unpackedRevert)
if revertReason, err := abi.UnpackRevertError(result.ReturnValue); err == nil {
return fmt.Errorf("%s contract call was reverted: %s", contractName, revertReason)
}
}

return fmt.Errorf("failed to initialize %s contract. Reason: %w", contractName, result.Err)
return fmt.Errorf("%s contract call failed: %w", contractName, result.Err)
}

return nil
Expand Down
36 changes: 31 additions & 5 deletions consensus/polybft/contractsapi/artifacts-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import (
"os"
"path"
"runtime"
"strings"

"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact"
"github.com/dave/jennifer/jen"

"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact"
)

const (
extension = ".sol"
)

func main() {
Expand Down Expand Up @@ -49,12 +55,16 @@ func main() {
},
{
"child/ChildERC20PredicateAccessList.sol",
"ChildERC20PredicateAccessList",
"ChildERC20PredicateACL",
},
{
"child/RootMintableERC20Predicate.sol",
"RootMintableERC20Predicate",
},
{
"child/RootMintableERC20PredicateAccessList.sol",
"RootMintableERC20PredicateACL",
},
{
"child/ChildERC721.sol",
"ChildERC721",
Expand All @@ -65,12 +75,16 @@ func main() {
},
{
"child/ChildERC721PredicateAccessList.sol",
"ChildERC721PredicateAccessList",
"ChildERC721PredicateACL",
},
{
"child/RootMintableERC721Predicate.sol",
"RootMintableERC721Predicate",
},
{
"child/RootMintableERC721PredicateAccessList.sol",
"RootMintableERC721PredicateACL",
},
{
"child/ChildERC1155.sol",
"ChildERC1155",
Expand All @@ -81,12 +95,16 @@ func main() {
},
{
"child/ChildERC1155PredicateAccessList.sol",
"ChildERC1155PredicateAccessList",
"ChildERC1155PredicateACL",
},
{
"child/RootMintableERC1155Predicate.sol",
"RootMintableERC1155Predicate",
},
{
"child/RootMintableERC1155PredicateAccessList.sol",
"RootMintableERC1155PredicateACL",
},
{
"child/System.sol",
"System",
Expand Down Expand Up @@ -170,7 +188,7 @@ func main() {
}

for _, v := range readContracts {
artifactBytes, err := artifact.ReadArtifactData(scpath, v.Path, v.Name)
artifactBytes, err := artifact.ReadArtifactData(scpath, v.Path, getContractName(v.Path))
if err != nil {
log.Fatal(err)
}
Expand All @@ -188,3 +206,11 @@ func main() {
log.Fatal(err)
}
}

// getContractName extracts smart contract name from provided path
func getContractName(path string) string {
pathSegments := strings.Split(path, string([]rune{os.PathSeparator}))
nameSegment := pathSegments[len(pathSegments)-1]

return strings.Split(nameSegment, extension)[0]
}
Loading

0 comments on commit 550852d

Please sign in to comment.