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 }