github.com/ChainSafe/chainbridge-core@v1.4.2/chains/evm/cli/deploy/deploy.go (about)

     1  package deploy
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  
     8  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls"
     9  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/bridge"
    10  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/erc20"
    11  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/erc721"
    12  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/generic"
    13  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/evmclient"
    14  	evmgaspricer "github.com/ChainSafe/chainbridge-core/chains/evm/calls/evmgaspricer"
    15  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/evmtransaction"
    16  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor/signAndSend"
    17  
    18  	"github.com/ChainSafe/chainbridge-core/chains/evm/cli/flags"
    19  	"github.com/ChainSafe/chainbridge-core/chains/evm/cli/logger"
    20  	"github.com/ChainSafe/chainbridge-core/chains/evm/cli/utils"
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/rs/zerolog/log"
    23  	"github.com/spf13/cobra"
    24  )
    25  
    26  var ErrNoDeploymentFlagsProvided = errors.New("provide at least one deployment flag. For help use --help")
    27  
    28  var DeployEVM = &cobra.Command{
    29  	Use:   "deploy",
    30  	Short: "Deploy smart contracts",
    31  	Long:  "This command can be used to deploy all or some of the contracts required for bridging. Selection of contracts can be made by either specifying --all or a subset of flags",
    32  	PreRun: func(cmd *cobra.Command, args []string) {
    33  		logger.LoggerMetadata(cmd.Name(), cmd.Flags())
    34  	},
    35  	RunE: CallDeployCLI,
    36  	Args: func(cmd *cobra.Command, args []string) error {
    37  		err := ValidateDeployFlags(cmd, args)
    38  		if err != nil {
    39  			return err
    40  		}
    41  		err = ProcessDeployFlags(cmd, args)
    42  		return err
    43  	},
    44  }
    45  
    46  const (
    47  	TwoDaysTermInBlocks int64 = 6200
    48  )
    49  
    50  var (
    51  	// Flags for all EVM Deploy CLI commands
    52  	Bridge           bool
    53  	BridgeAddress    string
    54  	DeployAll        bool
    55  	DomainId         uint8
    56  	GenericHandler   bool
    57  	Erc20            bool
    58  	Erc20Handler     bool
    59  	Erc20Name        string
    60  	Erc20Symbol      string
    61  	Erc721           bool
    62  	Erc721Handler    bool
    63  	Erc721Name       string
    64  	Erc721Symbol     string
    65  	Erc721BaseURI    string
    66  	Fee              uint64
    67  	RelayerThreshold uint64
    68  	Relayers         []string
    69  )
    70  
    71  func BindDeployEVMFlags(cmd *cobra.Command) {
    72  	cmd.Flags().BoolVar(&Bridge, "bridge", false, "Deploy bridge")
    73  	cmd.Flags().StringVar(&BridgeAddress, "bridge-address", "", "Bridge contract address. Should be provided if handlers are deployed separately")
    74  	cmd.Flags().BoolVar(&DeployAll, "all", false, "Deploy all")
    75  	cmd.Flags().Uint8Var(&DomainId, "domain", 1, "Domain ID for the instance")
    76  	cmd.Flags().BoolVar(&Erc20, "erc20", false, "Deploy ERC20")
    77  	cmd.Flags().BoolVar(&Erc20Handler, "erc20-handler", false, "Deploy ERC20 handler")
    78  	cmd.Flags().StringVar(&Erc20Name, "erc20-name", "", "ERC20 contract name")
    79  	cmd.Flags().StringVar(&Erc20Symbol, "erc20-symbol", "", "ERC20 contract symbol")
    80  	cmd.Flags().BoolVar(&Erc721, "erc721", false, "Deploy ERC721")
    81  	cmd.Flags().BoolVar(&Erc721Handler, "erc721-handler", false, "Deploy ERC721 handler")
    82  	cmd.Flags().StringVar(&Erc721Name, "erc721-name", "", "ERC721 contract name")
    83  	cmd.Flags().StringVar(&Erc721Symbol, "erc721-symbol", "", "ERC721 contract symbol")
    84  	cmd.Flags().StringVar(&Erc721BaseURI, "erc721-base-uri", "", "ERC721 base URI")
    85  	cmd.Flags().BoolVar(&GenericHandler, "generic-handler", false, "Deploy generic handler")
    86  	cmd.Flags().Uint64Var(&Fee, "fee", 0, "Fee to be taken when making a deposit (in ETH, decimals are allowed)")
    87  	cmd.Flags().StringSliceVar(&Relayers, "relayers", []string{}, "List of initial relayers")
    88  	cmd.Flags().Uint64Var(&RelayerThreshold, "relayer-threshold", 1, "Number of votes required for a proposal to pass")
    89  }
    90  
    91  func init() {
    92  	BindDeployEVMFlags(DeployEVM)
    93  }
    94  
    95  func ValidateDeployFlags(cmd *cobra.Command, args []string) error {
    96  	Deployments = make([]string, 0)
    97  	if DeployAll {
    98  		flags.MarkFlagsAsRequired(cmd, "relayer-threshold", "domain", "fee", "erc20-symbol", "erc20-name")
    99  		Deployments = append(Deployments, []string{"bridge", "erc20-handler", "erc721-handler", "generic-handler", "erc20", "erc721"}...)
   100  	} else {
   101  		if Bridge {
   102  			flags.MarkFlagsAsRequired(cmd, "relayer-threshold", "domain", "fee")
   103  			Deployments = append(Deployments, "bridge")
   104  		}
   105  		if Erc20Handler {
   106  			if !Bridge {
   107  				flags.MarkFlagsAsRequired(cmd, "bridge-address")
   108  			}
   109  			Deployments = append(Deployments, "erc20-handler")
   110  		}
   111  		if Erc721Handler {
   112  			if !Bridge {
   113  				flags.MarkFlagsAsRequired(cmd, "bridge-address")
   114  			}
   115  			Deployments = append(Deployments, "erc721-handler")
   116  		}
   117  		if GenericHandler {
   118  			if !Bridge {
   119  				flags.MarkFlagsAsRequired(cmd, "bridge-address")
   120  			}
   121  			Deployments = append(Deployments, "generic-handler")
   122  		}
   123  		if Erc20 {
   124  			flags.MarkFlagsAsRequired(cmd, "erc20-symbol", "erc20-name")
   125  			Deployments = append(Deployments, "erc20")
   126  		}
   127  		if Erc721 {
   128  			flags.MarkFlagsAsRequired(cmd, "erc721-name", "erc721-symbol", "erc721-base-uri")
   129  			Deployments = append(Deployments, "erc721")
   130  		}
   131  	}
   132  
   133  	if len(Deployments) == 0 {
   134  		log.Error().Err(ErrNoDeploymentFlagsProvided)
   135  		return ErrNoDeploymentFlagsProvided
   136  	}
   137  
   138  	return nil
   139  }
   140  
   141  var Deployments []string
   142  var BridgeAddr common.Address
   143  var RelayerAddresses []common.Address
   144  
   145  func ProcessDeployFlags(cmd *cobra.Command, args []string) error {
   146  	if common.IsHexAddress(BridgeAddress) {
   147  		BridgeAddr = common.HexToAddress(BridgeAddress)
   148  	}
   149  	for _, addr := range Relayers {
   150  		if !common.IsHexAddress(addr) {
   151  			return fmt.Errorf("invalid relayer address %s", addr)
   152  		}
   153  		RelayerAddresses = append(RelayerAddresses, common.HexToAddress(addr))
   154  	}
   155  	return nil
   156  }
   157  
   158  func CallDeployCLI(cmd *cobra.Command, args []string) error {
   159  	txFabric := evmtransaction.NewTransaction
   160  	return DeployCLI(cmd, args, txFabric, &evmgaspricer.LondonGasPriceDeterminant{})
   161  }
   162  
   163  func DeployCLI(cmd *cobra.Command, args []string, txFabric calls.TxFabric, gasPricer utils.GasPricerWithPostConfig) error {
   164  	// fetch global flag values
   165  	url, gasLimit, gasPrice, senderKeyPair, _, err := flags.GlobalFlagValues(cmd)
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	log.Debug().Msgf("url: %s gas limit: %v gas price: %v", url, gasLimit, gasPrice)
   171  	log.Debug().Msgf("SENDER Address %s", senderKeyPair.CommonAddress().Hex())
   172  
   173  	ethClient, err := evmclient.NewEVMClient(url, senderKeyPair)
   174  	if err != nil {
   175  		log.Error().Err(fmt.Errorf("ethereum client error: %v", err)).Msg("error initializing new EVM client")
   176  		return err
   177  	}
   178  	gasPricer.SetClient(ethClient)
   179  	gasPricer.SetOpts(&evmgaspricer.GasPricerOpts{UpperLimitFeePerGas: gasPrice})
   180  	log.Debug().Msgf("Relayers for deploy %+v", Relayers)
   181  	log.Debug().Msgf("all bool: %v", DeployAll)
   182  
   183  	t := signAndSend.NewSignAndSendTransactor(txFabric, gasPricer, ethClient)
   184  
   185  	deployedContracts := make(map[string]string)
   186  	for _, v := range Deployments {
   187  		switch v {
   188  		case "bridge":
   189  			log.Debug().Msgf("deploying bridge..")
   190  			bc := bridge.NewBridgeContract(ethClient, common.Address{}, t)
   191  			BridgeAddr, err = bc.DeployContract(
   192  				DomainId,
   193  				RelayerAddresses,
   194  				big.NewInt(0).SetUint64(RelayerThreshold),
   195  				big.NewInt(0).SetUint64(Fee),
   196  				big.NewInt(TwoDaysTermInBlocks), // _expiry is set to 48 hours by default
   197  			)
   198  			if err != nil {
   199  				log.Error().Err(fmt.Errorf("bridge deploy failed: %w", err))
   200  				return err
   201  			}
   202  			deployedContracts["bridge"] = BridgeAddr.String()
   203  			log.Debug().Msgf("bridge address; %v", BridgeAddr.String())
   204  		case "erc20":
   205  			log.Debug().Msgf("deploying ERC20..")
   206  			erc20Contract := erc20.NewERC20Contract(ethClient, common.Address{}, t)
   207  			erc20Addr, err := erc20Contract.DeployContract(Erc20Name, Erc20Symbol)
   208  			if err != nil {
   209  				log.Error().Err(fmt.Errorf("erc 20 deploy failed: %w", err))
   210  				return err
   211  			}
   212  			deployedContracts["erc20Token"] = erc20Addr.String()
   213  		case "erc20-handler":
   214  			log.Debug().Msgf("deploying ERC20 handler..")
   215  			erc20HandlerContract := erc20.NewERC20HandlerContract(ethClient, common.Address{}, t)
   216  			erc20HandlerAddr, err := erc20HandlerContract.DeployContract(BridgeAddr)
   217  			if err != nil {
   218  				log.Error().Err(fmt.Errorf("ERC20 handler deploy failed: %w", err))
   219  				return err
   220  			}
   221  			deployedContracts["erc20Handler"] = erc20HandlerAddr.String()
   222  		case "erc721":
   223  			log.Debug().Msgf("deploying ERC721..")
   224  			erc721Contract := erc721.NewErc721Contract(ethClient, common.Address{}, t)
   225  			erc721Addr, err := erc721Contract.DeployContract(Erc721Name, Erc721Symbol, Erc721BaseURI)
   226  			if err != nil {
   227  				log.Error().Err(fmt.Errorf("ERC721 deploy failed: %w", err))
   228  				return err
   229  			}
   230  			deployedContracts["erc721Token"] = erc721Addr.String()
   231  		case "erc721-handler":
   232  			log.Debug().Msgf("deploying ERC721 handler..")
   233  			erc721HandlerContract := erc721.NewERC721HandlerContract(ethClient, common.Address{}, t)
   234  			erc721HandlerAddr, err := erc721HandlerContract.DeployContract(BridgeAddr)
   235  			if err != nil {
   236  				log.Error().Err(fmt.Errorf("ERC721 handler deploy failed: %w", err))
   237  				return err
   238  			}
   239  			deployedContracts["erc721Handler"] = erc721HandlerAddr.String()
   240  		case "generic-handler":
   241  			log.Debug().Msgf("deploying generic handler..")
   242  			emptyAddr := common.Address{}
   243  			if BridgeAddr == emptyAddr {
   244  				log.Error().Err(errors.New("bridge flag or bridge-address param should be set for contracts Deployments"))
   245  				return err
   246  			}
   247  			genericHandlerContract := generic.NewGenericHandlerContract(ethClient, common.Address{}, t)
   248  			genericHandlerAddr, err := genericHandlerContract.DeployContract(BridgeAddr)
   249  			if err != nil {
   250  				log.Error().Err(fmt.Errorf("Generic handler deploy failed: %w", err))
   251  				return err
   252  			}
   253  			deployedContracts["genericHandler"] = genericHandlerAddr.String()
   254  		}
   255  	}
   256  	fmt.Printf(`
   257  	Deployed contracts
   258  =========================================================
   259  Bridge: %s
   260  ---------------------------------------------------------
   261  ERC20 Token: %s
   262  ---------------------------------------------------------
   263  ERC20 Handler: %s
   264  ---------------------------------------------------------
   265  ERC721 Token: %s
   266  ---------------------------------------------------------
   267  ERC721 Handler: %s
   268  ---------------------------------------------------------
   269  Generic Handler: %s
   270  =========================================================
   271  	`,
   272  		deployedContracts["bridge"],
   273  		deployedContracts["erc20Token"],
   274  		deployedContracts["erc20Handler"],
   275  		deployedContracts["erc721Token"],
   276  		deployedContracts["erc721Handler"],
   277  		deployedContracts["genericHandler"],
   278  	)
   279  	return nil
   280  }