Skip to content

Commit

Permalink
Add a flag to deploy command for stake manager address (0xPolygon#1520
Browse files Browse the repository at this point in the history
)

* Do not deploy stake manager if already deployed

* Command for deploying stake manager

* Parallel deployment in stake-manager-deploy command

* Comments fix
  • Loading branch information
goran-ethernal authored May 24, 2023
1 parent e859acf commit 2bef96a
Show file tree
Hide file tree
Showing 19 changed files with 486 additions and 148 deletions.
3 changes: 3 additions & 0 deletions command/polybft/polybft_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/0xPolygon/polygon-edge/command/rootchain/registration"
"github.com/0xPolygon/polygon-edge/command/rootchain/staking"
"github.com/0xPolygon/polygon-edge/command/rootchain/supernet"
"github.com/0xPolygon/polygon-edge/command/rootchain/supernet/stakemanager"
"github.com/0xPolygon/polygon-edge/command/rootchain/validators"
"github.com/0xPolygon/polygon-edge/command/rootchain/whitelist"
"github.com/0xPolygon/polygon-edge/command/rootchain/withdraw"
Expand Down Expand Up @@ -39,6 +40,8 @@ func GetCommand() *cobra.Command {
// rootchain (supernet manager) command for finalizing genesis
// validator set and enabling staking
supernet.GetCommand(),
// rootchain command for deploying stake manager
stakemanager.GetCommand(),
)

return polybftCmd
Expand Down
112 changes: 35 additions & 77 deletions command/rootchain/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const (
rootERC1155Name = "RootERC1155"
erc1155TemplateName = "ERC1155Template"
customSupernetManagerName = "CustomSupernetManager"
stakeManagerName = "StakeManager"
)

var (
Expand Down Expand Up @@ -97,21 +96,11 @@ var (
customSupernetManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.CustomSupernetManagerAddress = addr
},
stakeManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) {
rootchainConfig.StakeManagerAddress = addr
},
}

// initializersMap maps rootchain contract names to initializer function callbacks
initializersMap = map[string]func(command.OutputFormatter, txrelayer.TxRelayer,
*polybft.RootchainConfig, ethgo.Key) error{
stakeManagerName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
key ethgo.Key) error {

return initializeStakeManager(fmt, relayer, config, key)
},
customSupernetManagerName: func(fmt command.OutputFormatter,
relayer txrelayer.TxRelayer,
config *polybft.RootchainConfig,
Expand Down Expand Up @@ -209,7 +198,15 @@ func GetCommand() *cobra.Command {
" (otherwise provided secrets are used to resolve deployer account)",
)

cmd.Flags().StringVar(
&params.stakeManagerAddr,
helper.StakeManagerFlag,
"",
helper.StakeManagerFlagDesc,
)

cmd.MarkFlagsMutuallyExclusive(helper.TestModeFlag, deployerKeyFlag)
_ = cmd.MarkFlagRequired(helper.StakeManagerFlag)

return cmd
}
Expand All @@ -222,7 +219,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
outputter := command.InitializeOutputter(cmd)
defer outputter.WriteOutput()

outputter.WriteCommandResult(&messageResult{
outputter.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s started... Rootchain JSON RPC address %s.", contractsDeploymentTitle, params.jsonRPCAddress),
})

Expand Down Expand Up @@ -255,7 +252,7 @@ func runCommand(cmd *cobra.Command, _ []string) {

return
} else if code != "0x" {
outputter.SetCommandResult(&messageResult{
outputter.SetCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s contracts are already deployed. Aborting.", contractsDeploymentTitle),
})

Expand All @@ -272,7 +269,15 @@ func runCommand(cmd *cobra.Command, _ []string) {
}

// populate bridge configuration
consensusConfig.Bridge = rootchainCfg.ToBridgeConfig()
bridgeConfig := rootchainCfg.ToBridgeConfig()
if consensusConfig.Bridge != nil {
// only true if stake-manager-deploy command was executed
// users can still deploy stake manager manually
// only used for e2e tests
bridgeConfig.StakeTokenAddr = consensusConfig.Bridge.StakeTokenAddr
}

consensusConfig.Bridge = bridgeConfig

// set event tracker start blocks for rootchain contract(s) of interest
blockNum, err := client.Eth().BlockNumber()
Expand All @@ -296,7 +301,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
return
}

outputter.SetCommandResult(&messageResult{
outputter.SetCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s finished. All contracts are successfully deployed and initialized.",
contractsDeploymentTitle),
})
Expand Down Expand Up @@ -331,6 +336,8 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client,

rootchainConfig := &polybft.RootchainConfig{
JSONRPCAddr: params.jsonRPCAddress,
// update stake manager address in genesis in case if stake manager was deployed manually
StakeManagerAddress: types.StringToAddress(params.stakeManagerAddr),
}

tokenContracts := []*contractInfo{}
Expand Down Expand Up @@ -416,10 +423,6 @@ func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client,
name: erc1155TemplateName,
artifact: contractsapi.ChildERC1155,
},
{
name: stakeManagerName,
artifact: contractsapi.StakeManager,
},
{
name: customSupernetManagerName,
artifact: contractsapi.CustomSupernetManager,
Expand Down Expand Up @@ -562,7 +565,7 @@ func registerChainOnStakeManager(txRelayer txrelayer.TxRelayer,
return 0, fmt.Errorf("failed to encode parameters for registering child chain on supernets. error: %w", err)
}

receipt, err := sendTransaction(txRelayer, ethgo.Address(rootchainCfg.StakeManagerAddress),
receipt, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainCfg.StakeManagerAddress),
encoded, checkpointManagerName, deployerKey)
if err != nil {
return 0, err
Expand Down Expand Up @@ -624,11 +627,11 @@ func initializeCheckpointManager(

addr := ethgo.Address(rootchainCfg.CheckpointManagerAddress)

if _, err = sendTransaction(txRelayer, addr, input, checkpointManagerName, deployerKey); err != nil {
if _, err = helper.SendTransaction(txRelayer, addr, input, checkpointManagerName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
cmdOutput.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, checkpointManagerName),
})

Expand All @@ -646,12 +649,12 @@ func initializeExitHelper(cmdOutput command.OutputFormatter,
return fmt.Errorf("failed to encode parameters for ExitHelper.initialize. error: %w", err)
}

if _, err = sendTransaction(txRelayer, ethgo.Address(rootchainConfig.ExitHelperAddress),
if _, err = helper.SendTransaction(txRelayer, ethgo.Address(rootchainConfig.ExitHelperAddress),
input, exitHelperName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
cmdOutput.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, exitHelperName),
})

Expand All @@ -674,13 +677,13 @@ func initializeRootERC20Predicate(cmdOutput command.OutputFormatter, txRelayer t
return fmt.Errorf("failed to encode parameters for RootERC20Predicate.initialize. error: %w", err)
}

if _, err := sendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC20PredicateAddress),
if _, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC20PredicateAddress),
input, rootERC20PredicateName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(
&messageResult{
&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, rootERC20PredicateName),
})

Expand All @@ -701,12 +704,12 @@ func initializeRootERC721Predicate(cmdOutput command.OutputFormatter, txRelayer
return fmt.Errorf("failed to encode parameters for RootERC721Predicate.initialize. error: %w", err)
}

if _, err := sendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC721PredicateAddress),
if _, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC721PredicateAddress),
input, rootERC721PredicateName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
cmdOutput.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, rootERC721PredicateName),
})

Expand All @@ -728,42 +731,18 @@ func initializeRootERC1155Predicate(cmdOutput command.OutputFormatter, txRelayer
return fmt.Errorf("failed to encode parameters for RootERC1155Predicate.initialize. error: %w", err)
}

if _, err := sendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC1155PredicateAddress),
if _, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainConfig.RootERC1155PredicateAddress),
input, rootERC1155PredicateName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
cmdOutput.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, rootERC1155PredicateName),
})

return nil
}

// initializeStakeManager invokes initialize function on StakeManager contract
func initializeStakeManager(cmdOutput command.OutputFormatter,
txRelayer txrelayer.TxRelayer,
rootchainConfig *polybft.RootchainConfig,
deployerKey ethgo.Key) error {
initFn := &contractsapi.InitializeStakeManagerFn{MATIC_: rootchainConfig.RootNativeERC20Address}

input, err := initFn.EncodeAbi()
if err != nil {
return err
}

if _, err := sendTransaction(txRelayer, ethgo.Address(rootchainConfig.StakeManagerAddress),
input, stakeManagerName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, stakeManagerName),
})

return nil
}

// initializeSupernetManager invokes initialize function on CustomSupernetManager contract
func initializeSupernetManager(cmdOutput command.OutputFormatter,
txRelayer txrelayer.TxRelayer, rootchainConfig *polybft.RootchainConfig,
Expand All @@ -783,39 +762,18 @@ func initializeSupernetManager(cmdOutput command.OutputFormatter,
return err
}

if _, err := sendTransaction(txRelayer, ethgo.Address(rootchainConfig.CustomSupernetManagerAddress),
if _, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainConfig.CustomSupernetManagerAddress),
input, customSupernetManagerName, deployerKey); err != nil {
return err
}

cmdOutput.WriteCommandResult(&messageResult{
cmdOutput.WriteCommandResult(&helper.MessageResult{
Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, customSupernetManagerName),
})

return nil
}

// sendTransaction sends provided transaction
func sendTransaction(txRelayer txrelayer.TxRelayer, addr ethgo.Address, input []byte, contractName string,
deployerKey ethgo.Key) (*ethgo.Receipt, error) {
txn := &ethgo.Transaction{
To: &addr,
Input: input,
}

receipt, err := txRelayer.SendTransaction(txn, deployerKey)
if err != nil {
return nil, fmt.Errorf("failed to send transaction to %s contract (%s). error: %w",
contractName, txn.To.Address(), err)
}

if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) {
return nil, fmt.Errorf("transaction execution failed on %s contract", contractName)
}

return receipt, nil
}

// validatorSetToABISlice converts given validators to generic map
// which is used for ABI encoding validator set being sent to the rootchain contract
func validatorSetToABISlice(o command.OutputFormatter,
Expand Down
12 changes: 12 additions & 0 deletions command/rootchain/deploy/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"testing"

"github.com/stretchr/testify/require"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/jsonrpc"
"github.com/umbracle/ethgo/testutil"

"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
"github.com/0xPolygon/polygon-edge/consensus/polybft/validator"
"github.com/0xPolygon/polygon-edge/types"
)
Expand All @@ -35,7 +37,17 @@ func TestDeployContracts_NoPanics(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status)

txn := &ethgo.Transaction{
To: nil, // contract deployment
Input: contractsapi.StakeManager.Bytecode,
}

receipt, err = server.SendTxn(txn)
require.NoError(t, err)
require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status)

outputter := command.InitializeOutputter(GetCommand())
params.stakeManagerAddr = receipt.ContractAddress.String()

require.NotPanics(t, func() {
_, _, err = deployContracts(outputter, client, 1, []*validator.GenesisValidator{}, context.Background())
Expand Down
1 change: 1 addition & 0 deletions command/rootchain/deploy/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type deployParams struct {
rootERC20TokenAddr string
rootERC721TokenAddr string
rootERC1155TokenAddr string
stakeManagerAddr string
isTestMode bool
}

Expand Down
13 changes: 0 additions & 13 deletions command/rootchain/deploy/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,3 @@ func (r deployContractResult) GetOutput() string {

return buffer.String()
}

type messageResult struct {
Message string `json:"message"`
}

func (r messageResult) GetOutput() string {
var buffer bytes.Buffer

buffer.WriteString(r.Message)
buffer.WriteString("\n")

return buffer.String()
}
Loading

0 comments on commit 2bef96a

Please sign in to comment.