github.com/ChainSafe/chainbridge-core@v1.4.2/chains/evm/calls/contracts/bridge/bridge.go (about)

     1  package bridge
     2  
     3  import (
     4  	"bytes"
     5  	"math/big"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls"
    10  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/consts"
    11  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts"
    12  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/deposit"
    13  	"github.com/ChainSafe/chainbridge-core/chains/evm/calls/transactor"
    14  	"github.com/ethereum/go-ethereum/common/hexutil"
    15  
    16  	"github.com/ChainSafe/chainbridge-core/chains/evm/executor/proposal"
    17  	"github.com/ChainSafe/chainbridge-core/relayer/message"
    18  	"github.com/ChainSafe/chainbridge-core/types"
    19  	"github.com/ethereum/go-ethereum/accounts/abi"
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/rs/zerolog/log"
    22  )
    23  
    24  type BridgeContract struct {
    25  	contracts.Contract
    26  }
    27  
    28  func NewBridgeContract(
    29  	client calls.ContractCallerDispatcher,
    30  	bridgeContractAddress common.Address,
    31  	transactor transactor.Transactor,
    32  ) *BridgeContract {
    33  	a, _ := abi.JSON(strings.NewReader(consts.BridgeABI))
    34  	b := common.FromHex(consts.BridgeBin)
    35  	return &BridgeContract{contracts.NewContract(bridgeContractAddress, a, b, client, transactor)}
    36  }
    37  
    38  func (c *BridgeContract) AddRelayer(
    39  	relayerAddr common.Address,
    40  	opts transactor.TransactOptions,
    41  ) (*common.Hash, error) {
    42  	log.Debug().Msgf("Adding new relayer %s", relayerAddr.String())
    43  	return c.ExecuteTransaction(
    44  		"adminAddRelayer",
    45  		opts,
    46  		relayerAddr,
    47  	)
    48  }
    49  
    50  func (c *BridgeContract) AdminSetGenericResource(
    51  	handler common.Address,
    52  	rID types.ResourceID,
    53  	addr common.Address,
    54  	depositFunctionSig [4]byte,
    55  	depositerOffset *big.Int,
    56  	executeFunctionSig [4]byte,
    57  	opts transactor.TransactOptions,
    58  ) (*common.Hash, error) {
    59  	log.Debug().Msgf("Setting generic resource %s", hexutil.Encode(rID[:]))
    60  	return c.ExecuteTransaction(
    61  		"adminSetGenericResource",
    62  		opts,
    63  		handler, rID, addr, depositFunctionSig, depositerOffset, executeFunctionSig,
    64  	)
    65  }
    66  
    67  func (c *BridgeContract) AdminSetResource(
    68  	handlerAddr common.Address,
    69  	rID types.ResourceID,
    70  	targetContractAddr common.Address,
    71  	opts transactor.TransactOptions,
    72  ) (*common.Hash, error) {
    73  	log.Debug().Msgf("Setting resource %s", hexutil.Encode(rID[:]))
    74  	return c.ExecuteTransaction(
    75  		"adminSetResource",
    76  		opts,
    77  		handlerAddr, rID, targetContractAddr,
    78  	)
    79  }
    80  
    81  func (c *BridgeContract) SetDepositNonce(
    82  	domainId uint8,
    83  	depositNonce uint64,
    84  	opts transactor.TransactOptions,
    85  ) (*common.Hash, error) {
    86  	log.Debug().Msgf("Setting deposit nonce %d for %d", depositNonce, domainId)
    87  	return c.ExecuteTransaction(
    88  		"adminSetDepositNonce",
    89  		opts,
    90  		domainId, depositNonce,
    91  	)
    92  }
    93  
    94  func (c *BridgeContract) AdminChangeRelayerThreshold(
    95  	threshold uint64,
    96  	opts transactor.TransactOptions,
    97  ) (*common.Hash, error) {
    98  	log.Debug().Msgf("Setting threshold %d", threshold)
    99  	return c.ExecuteTransaction(
   100  		"adminChangeRelayerThreshold",
   101  		opts,
   102  		big.NewInt(0).SetUint64(threshold),
   103  	)
   104  }
   105  
   106  func (c *BridgeContract) SetBurnableInput(
   107  	handlerAddr common.Address,
   108  	tokenContractAddr common.Address,
   109  	opts transactor.TransactOptions,
   110  ) (*common.Hash, error) {
   111  	log.Debug().Msgf("Setting burnable input for %s", tokenContractAddr.String())
   112  	return c.ExecuteTransaction(
   113  		"adminSetBurnable",
   114  		opts,
   115  		handlerAddr, tokenContractAddr,
   116  	)
   117  }
   118  
   119  func (c *BridgeContract) deposit(
   120  	resourceID types.ResourceID,
   121  	destDomainID uint8,
   122  	data []byte,
   123  	opts transactor.TransactOptions,
   124  ) (*common.Hash, error) {
   125  	return c.ExecuteTransaction(
   126  		"deposit",
   127  		opts,
   128  		destDomainID, resourceID, data,
   129  	)
   130  }
   131  
   132  func (c *BridgeContract) Erc20Deposit(
   133  	recipient common.Address,
   134  	amount *big.Int,
   135  	resourceID types.ResourceID,
   136  	destDomainID uint8,
   137  	opts transactor.TransactOptions,
   138  ) (*common.Hash, error) {
   139  	log.Debug().
   140  		Str("recipient", recipient.String()).
   141  		Str("resourceID", hexutil.Encode(resourceID[:])).
   142  		Str("amount", amount.String()).
   143  		Msgf("ERC20 deposit")
   144  	var data []byte
   145  	if opts.Priority == 0 {
   146  		data = deposit.ConstructErc20DepositData(recipient.Bytes(), amount)
   147  	} else {
   148  		data = deposit.ConstructErc20DepositDataWithPriority(recipient.Bytes(), amount, opts.Priority)
   149  	}
   150  	txHash, err := c.deposit(resourceID, destDomainID, data, opts)
   151  	if err != nil {
   152  		log.Error().Err(err)
   153  		return nil, err
   154  	}
   155  	return txHash, err
   156  }
   157  
   158  func (c *BridgeContract) Erc721Deposit(
   159  	tokenId *big.Int,
   160  	metadata string,
   161  	recipient common.Address,
   162  	resourceID types.ResourceID,
   163  	destDomainID uint8,
   164  	opts transactor.TransactOptions,
   165  ) (*common.Hash, error) {
   166  	log.Debug().
   167  		Str("recipient", recipient.String()).
   168  		Str("resourceID", hexutil.Encode(resourceID[:])).
   169  		Str("tokenID", tokenId.String()).
   170  		Msgf("ERC721 deposit")
   171  	var data []byte
   172  	if opts.Priority == 0 {
   173  		data = deposit.ConstructErc721DepositData(recipient.Bytes(), tokenId, []byte(metadata))
   174  	} else {
   175  		data = deposit.ConstructErc721DepositDataWithPriority(recipient.Bytes(), tokenId, []byte(metadata), opts.Priority)
   176  	}
   177  	txHash, err := c.deposit(resourceID, destDomainID, data, opts)
   178  	if err != nil {
   179  		log.Error().Err(err)
   180  		return nil, err
   181  	}
   182  	return txHash, err
   183  }
   184  
   185  func (c *BridgeContract) GenericDeposit(
   186  	metadata []byte,
   187  	resourceID types.ResourceID,
   188  	destDomainID uint8,
   189  	opts transactor.TransactOptions,
   190  ) (*common.Hash, error) {
   191  	log.Debug().
   192  		Str("resourceID", hexutil.Encode(resourceID[:])).
   193  		Msgf("Generic deposit")
   194  	data := deposit.ConstructGenericDepositData(metadata)
   195  	txHash, err := c.deposit(resourceID, destDomainID, data, opts)
   196  	if err != nil {
   197  		log.Error().Err(err)
   198  		return nil, err
   199  	}
   200  	return txHash, err
   201  }
   202  
   203  func (c *BridgeContract) ExecuteProposal(
   204  	proposal *proposal.Proposal,
   205  	opts transactor.TransactOptions,
   206  ) (*common.Hash, error) {
   207  	log.Debug().
   208  		Str("depositNonce", strconv.FormatUint(proposal.DepositNonce, 10)).
   209  		Str("resourceID", hexutil.Encode(proposal.ResourceId[:])).
   210  		Str("handler", proposal.HandlerAddress.String()).
   211  		Msgf("Execute proposal")
   212  	return c.ExecuteTransaction(
   213  		"executeProposal",
   214  		opts,
   215  		proposal.Source, proposal.DepositNonce, proposal.Data, proposal.ResourceId, true,
   216  	)
   217  }
   218  
   219  func (c *BridgeContract) VoteProposal(
   220  	proposal *proposal.Proposal,
   221  	opts transactor.TransactOptions,
   222  ) (*common.Hash, error) {
   223  	log.Debug().
   224  		Str("depositNonce", strconv.FormatUint(proposal.DepositNonce, 10)).
   225  		Str("resourceID", hexutil.Encode(proposal.ResourceId[:])).
   226  		Str("handler", proposal.HandlerAddress.String()).
   227  		Msgf("Vote proposal")
   228  	return c.ExecuteTransaction(
   229  		"voteProposal",
   230  		opts,
   231  		proposal.Source, proposal.DepositNonce, proposal.ResourceId, proposal.Data,
   232  	)
   233  }
   234  
   235  func (c *BridgeContract) SimulateVoteProposal(proposal *proposal.Proposal) error {
   236  	log.Debug().
   237  		Str("depositNonce", strconv.FormatUint(proposal.DepositNonce, 10)).
   238  		Str("resourceID", hexutil.Encode(proposal.ResourceId[:])).
   239  		Str("handler", proposal.HandlerAddress.String()).
   240  		Msgf("Simulate vote proposal")
   241  	_, err := c.CallContract(
   242  		"voteProposal",
   243  		proposal.Source, proposal.DepositNonce, proposal.ResourceId, proposal.Data,
   244  	)
   245  	return err
   246  }
   247  
   248  func (c *BridgeContract) Pause(opts transactor.TransactOptions) (*common.Hash, error) {
   249  	log.Debug().Msg("Pause transfers")
   250  	return c.ExecuteTransaction(
   251  		"adminPauseTransfers",
   252  		opts,
   253  	)
   254  }
   255  
   256  func (c *BridgeContract) Unpause(opts transactor.TransactOptions) (*common.Hash, error) {
   257  	log.Debug().Msg("Unpause transfers")
   258  	return c.ExecuteTransaction(
   259  		"adminUnpauseTransfers",
   260  		opts,
   261  	)
   262  }
   263  
   264  func (c *BridgeContract) Withdraw(
   265  	handlerAddress,
   266  	tokenAddress,
   267  	recipientAddress common.Address,
   268  	amountOrTokenId *big.Int,
   269  	opts transactor.TransactOptions,
   270  ) (*common.Hash, error) {
   271  	// @dev withdrawal data should include:
   272  	// tokenAddress
   273  	// recipientAddress
   274  	// realAmount
   275  	data := bytes.Buffer{}
   276  	data.Write(common.LeftPadBytes(tokenAddress.Bytes(), 32))
   277  	data.Write(common.LeftPadBytes(recipientAddress.Bytes(), 32))
   278  	data.Write(common.LeftPadBytes(amountOrTokenId.Bytes(), 32))
   279  
   280  	return c.ExecuteTransaction("adminWithdraw", opts, handlerAddress, data.Bytes())
   281  }
   282  
   283  func (c *BridgeContract) GetThreshold() (uint8, error) {
   284  	log.Debug().Msg("Getting threshold")
   285  	res, err := c.CallContract("_relayerThreshold")
   286  	if err != nil {
   287  		return 0, err
   288  	}
   289  	out := *abi.ConvertType(res[0], new(uint8)).(*uint8)
   290  	return out, nil
   291  }
   292  
   293  func (c *BridgeContract) IsRelayer(relayerAddress common.Address) (bool, error) {
   294  	log.Debug().Msgf("Getting is %s a relayer", relayerAddress.String())
   295  	res, err := c.CallContract("isRelayer", relayerAddress)
   296  	if err != nil {
   297  		return false, err
   298  	}
   299  	out := abi.ConvertType(res[0], new(bool)).(*bool)
   300  	return *out, nil
   301  }
   302  
   303  func (c *BridgeContract) ProposalStatus(p *proposal.Proposal) (message.ProposalStatus, error) {
   304  	log.Debug().
   305  		Str("depositNonce", strconv.FormatUint(p.DepositNonce, 10)).
   306  		Str("resourceID", hexutil.Encode(p.ResourceId[:])).
   307  		Str("handler", p.HandlerAddress.String()).
   308  		Msg("Getting proposal status")
   309  	res, err := c.CallContract("getProposal", p.Source, p.DepositNonce, p.GetDataHash())
   310  	if err != nil {
   311  		return message.ProposalStatus{}, err
   312  	}
   313  	out := *abi.ConvertType(res[0], new(message.ProposalStatus)).(*message.ProposalStatus)
   314  	return out, nil
   315  }
   316  
   317  func (c *BridgeContract) IsProposalVotedBy(by common.Address, p *proposal.Proposal) (bool, error) {
   318  	log.Debug().
   319  		Str("depositNonce", strconv.FormatUint(p.DepositNonce, 10)).
   320  		Str("resourceID", hexutil.Encode(p.ResourceId[:])).
   321  		Str("handler", p.HandlerAddress.String()).
   322  		Msgf("Getting is proposal voted by %s", by.String())
   323  	res, err := c.CallContract("_hasVotedOnProposal", idAndNonce(p.Source, p.DepositNonce), p.GetDataHash(), by)
   324  	if err != nil {
   325  		return false, err
   326  	}
   327  	out := *abi.ConvertType(res[0], new(bool)).(*bool)
   328  	return out, nil
   329  }
   330  
   331  func (c *BridgeContract) GetHandlerAddressForResourceID(
   332  	resourceID types.ResourceID,
   333  ) (common.Address, error) {
   334  	log.Debug().Msgf("Getting handler address for resource %s", hexutil.Encode(resourceID[:]))
   335  	res, err := c.CallContract("_resourceIDToHandlerAddress", resourceID)
   336  	if err != nil {
   337  		return common.Address{}, err
   338  	}
   339  	out := *abi.ConvertType(res[0], new(common.Address)).(*common.Address)
   340  	return out, nil
   341  }
   342  
   343  func idAndNonce(srcId uint8, nonce uint64) *big.Int {
   344  	var data []byte
   345  	data = append(data, big.NewInt(int64(nonce)).Bytes()...)
   346  	data = append(data, uint8(srcId))
   347  	return big.NewInt(0).SetBytes(data)
   348  }