github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/blockchain/celo.go (about) 1 package blockchain 2 3 import ( 4 "context" 5 "fmt" 6 "math/big" 7 "strings" 8 9 "github.com/ethereum/go-ethereum/accounts/abi/bind" 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/core/types" 12 "github.com/ethereum/go-ethereum/crypto" 13 "github.com/rs/zerolog/log" 14 15 "github.com/smartcontractkit/chainlink-testing-framework/libs/utils/conversions" 16 ) 17 18 // Handles specific issues with the Celo EVM chain: https://docs.celo.org/ 19 20 // CeloMultinodeClient represents a multi-node, EVM compatible client for the Celo network 21 type CeloMultinodeClient struct { 22 *EthereumMultinodeClient 23 } 24 25 // CeloClient represents a single node, EVM compatible client for the Celo network 26 type CeloClient struct { 27 *EthereumClient 28 } 29 30 // DeployContract uses legacy txs for Celo to bypass Geth checking Celo headers which do not have a required 31 // sha3Uncles field 32 func (e *CeloClient) DeployContract( 33 contractName string, 34 deployer ContractDeployer, 35 ) (*common.Address, *types.Transaction, interface{}, error) { 36 suggestedPrice, err := e.Client.SuggestGasPrice(context.Background()) 37 if err != nil { 38 return nil, nil, nil, err 39 } 40 gasPriceBuffer := big.NewInt(0).SetUint64(e.NetworkConfig.GasEstimationBuffer) 41 42 opts, err := e.TransactionOpts(e.DefaultWallet) 43 if err != nil { 44 return nil, nil, nil, err 45 } 46 opts.GasPrice = suggestedPrice.Add(gasPriceBuffer, suggestedPrice) 47 48 contractAddress, transaction, contractInstance, err := deployer(opts, e.Client) 49 if err != nil { 50 if strings.Contains(err.Error(), "nonce") { 51 err = fmt.Errorf("using nonce %d err: %w", opts.Nonce.Uint64(), err) 52 } 53 return nil, nil, nil, err 54 } 55 56 if err = e.ProcessTransaction(transaction); err != nil { 57 return nil, nil, nil, err 58 } 59 60 log.Info(). 61 Str("Contract Address", contractAddress.Hex()). 62 Str("Contract Name", contractName). 63 Str("From", e.DefaultWallet.Address()). 64 Str("Total Gas Cost (CELO)", conversions.WeiToEther(transaction.Cost()).String()). 65 Str("Network Name", e.NetworkConfig.Name). 66 Msg("Deployed contract") 67 return &contractAddress, transaction, contractInstance, err 68 } 69 70 func (e *CeloClient) TransactionOpts(from *EthereumWallet) (*bind.TransactOpts, error) { 71 privateKey, err := crypto.HexToECDSA(from.PrivateKey()) 72 if err != nil { 73 return nil, fmt.Errorf("invalid private key: %w", err) 74 } 75 opts, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(e.NetworkConfig.ChainID)) 76 if err != nil { 77 return nil, err 78 } 79 opts.From = common.HexToAddress(from.Address()) 80 opts.Context = context.Background() 81 82 nonce, err := e.GetNonce(context.Background(), common.HexToAddress(from.Address())) 83 if err != nil { 84 return nil, err 85 } 86 opts.Nonce = big.NewInt(int64(nonce)) 87 88 gasPrice, err := e.Client.SuggestGasPrice(context.Background()) 89 if err != nil { 90 return nil, err 91 } 92 gasPriceBuffer := big.NewInt(0).SetUint64(e.NetworkConfig.GasEstimationBuffer) 93 opts.GasPrice = gasPrice.Add(gasPriceBuffer, gasPrice) 94 95 if e.NetworkConfig.MinimumConfirmations <= 0 { // Wait for your turn to send on an L2 chain 96 <-e.NonceSettings.registerInstantTransaction(from.Address(), nonce) 97 } 98 return opts, nil 99 }