diff --git a/integration-tests/LOG_POLLER.md b/integration-tests/LOG_POLLER.md index 3d6f4b78cef..ab46838eb32 100644 --- a/integration-tests/LOG_POLLER.md +++ b/integration-tests/LOG_POLLER.md @@ -121,7 +121,7 @@ Various checks inside the tests have hardcoded timeouts, which might not be suit Sample snippet: ``` gom.Eventually(func(g gomega.Gomega) { - logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster) + logCountMatches, err := ClNodesHaveExpectedLogCount(startBlock, endBlock int64, chainID *big.Int, expectedLogCount int, expectedFilters []ExpectedFilter, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) { if err != nil { l.Warn().Err(err).Msg("Error checking if CL nodes have expected log count. Retrying...") } diff --git a/integration-tests/README_SETH.md b/integration-tests/README_SETH.md index bd66b62057b..92302ab9ce7 100644 --- a/integration-tests/README_SETH.md +++ b/integration-tests/README_SETH.md @@ -461,4 +461,4 @@ Currently, Seth doesn't support splitting non-native tokens between keys. If you 3. **Prepare payload for Multicall contract** that will call `transfer` function on the token contract for each key. 4. **Execute Multicall contract** with the payload prepared in the previous step. -You can find sample code for doing that for LINK token in [actions_seth](./actions/seth/actions.go) file as `SendLinkFundsToDeploymentAddresses()` method. +You can find sample code for doing that for LINK token in [actions](./actions/actions.go) file as `SendLinkFundsToDeploymentAddresses()` method. diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 2a55ae5b946..6c3ae0f6069 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -4,276 +4,670 @@ package actions import ( "context" "crypto/ecdsa" - "encoding/hex" - "encoding/json" - "errors" "fmt" "math/big" - "os" "strings" "sync" "testing" "time" + geth "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/rpc" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/go-resty/resty/v2" "github.com/rs/zerolog" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/rs/zerolog/log" - "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/test-go/testify/require" + "math" + "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" ) -// ContractDeploymentInterval After how many contract actions to wait before starting any more -// Example: When deploying 1000 contracts, stop every ContractDeploymentInterval have been deployed to wait before continuing -var ContractDeploymentInterval = 200 - -// FundChainlinkNodes will fund all of the provided Chainlink nodes with a set amountCreateOCRv2Jobs of native currency -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.FundChainlinkNodes -func FundChainlinkNodes( - nodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, - amount *big.Float, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() +// ChainlinkNodeAddresses will return all the on-chain wallet addresses for a set of Chainlink nodes +func ChainlinkNodeAddresses(nodes []*client.ChainlinkK8sClient) ([]common.Address, error) { + addresses := make([]common.Address, 0) + for _, node := range nodes { + primaryAddress, err := node.PrimaryEthAddress() if err != nil { - return err - } - recipient := common.HexToAddress(toAddress) - msg := ethereum.CallMsg{ - From: common.HexToAddress(client.GetDefaultWallet().Address()), - To: &recipient, - Value: conversions.EtherToWei(amount), + return nil, err } - gasEstimates, err := client.EstimateGas(msg) + addresses = append(addresses, common.HexToAddress(primaryAddress)) + } + return addresses, nil +} + +// ChainlinkNodeAddressesAtIndex will return all the on-chain wallet addresses for a set of Chainlink nodes +func ChainlinkNodeAddressesAtIndex(nodes []*client.ChainlinkK8sClient, keyIndex int) ([]common.Address, error) { + addresses := make([]common.Address, 0) + for _, node := range nodes { + nodeAddresses, err := node.EthAddresses() if err != nil { - return err + return nil, err } - err = client.Fund(toAddress, amount, gasEstimates) - if err != nil { - return err + addresses = append(addresses, common.HexToAddress(nodeAddresses[keyIndex])) + } + return addresses, nil +} + +// EncodeOnChainVRFProvingKey encodes uncompressed public VRF key to on-chain representation +func EncodeOnChainVRFProvingKey(vrfKey client.VRFKey) ([2]*big.Int, error) { + uncompressed := vrfKey.Data.Attributes.Uncompressed + provingKey := [2]*big.Int{} + var set1 bool + var set2 bool + // strip 0x to convert to int + provingKey[0], set1 = new(big.Int).SetString(uncompressed[2:66], 16) + if !set1 { + return [2]*big.Int{}, fmt.Errorf("can not convert VRF key to *big.Int") + } + provingKey[1], set2 = new(big.Int).SetString(uncompressed[66:], 16) + if !set2 { + return [2]*big.Int{}, fmt.Errorf("can not convert VRF key to *big.Int") + } + return provingKey, nil +} + +// EncodeOnChainExternalJobID encodes external job uuid to on-chain representation +func EncodeOnChainExternalJobID(jobID uuid.UUID) [32]byte { + var ji [32]byte + copy(ji[:], strings.Replace(jobID.String(), "-", "", 4)) + return ji +} + +// todo - move to CTF +func GenerateWallet() (common.Address, error) { + privateKey, err := crypto.GenerateKey() + if err != nil { + return common.Address{}, err + } + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return common.Address{}, fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey") + } + return crypto.PubkeyToAddress(*publicKeyECDSA), nil +} + +// todo - move to CTF +func GetTxFromAddress(tx *types.Transaction) (string, error) { + from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) + return from.String(), err +} + +// todo - move to CTF +func DecodeTxInputData(abiString string, data []byte) (map[string]interface{}, error) { + jsonABI, err := abi.JSON(strings.NewReader(abiString)) + if err != nil { + return nil, err + } + methodSigData := data[:4] + inputsSigData := data[4:] + method, err := jsonABI.MethodById(methodSigData) + if err != nil { + return nil, err + } + inputsMap := make(map[string]interface{}) + if err := method.Inputs.UnpackIntoMap(inputsMap, inputsSigData); err != nil { + return nil, err + } + return inputsMap, nil +} + +// todo - move to CTF +func WaitForBlockNumberToBe( + waitForBlockNumberToBe uint64, + client *seth.Client, + wg *sync.WaitGroup, + timeout time.Duration, + t testing.TB, + l zerolog.Logger, +) (uint64, error) { + blockNumberChannel := make(chan uint64) + errorChannel := make(chan error) + testContext, testCancel := context.WithTimeout(context.Background(), timeout) + defer testCancel() + ticker := time.NewTicker(time.Second * 5) + var latestBlockNumber uint64 + for { + select { + case <-testContext.Done(): + ticker.Stop() + wg.Done() + return latestBlockNumber, + fmt.Errorf("timeout waiting for Block Number to be: %d. Last recorded block number was: %d", + waitForBlockNumberToBe, latestBlockNumber) + case <-ticker.C: + go func() { + currentBlockNumber, err := client.Client.BlockNumber(testcontext.Get(t)) + if err != nil { + errorChannel <- err + } + l.Info(). + Uint64("Latest Block Number", currentBlockNumber). + Uint64("Desired Block Number", waitForBlockNumberToBe). + Msg("Waiting for Block Number to be") + blockNumberChannel <- currentBlockNumber + }() + case latestBlockNumber = <-blockNumberChannel: + if latestBlockNumber >= waitForBlockNumberToBe { + ticker.Stop() + wg.Done() + l.Info(). + Uint64("Latest Block Number", latestBlockNumber). + Uint64("Desired Block Number", waitForBlockNumberToBe). + Msg("Desired Block Number reached!") + return latestBlockNumber, nil + } + case err := <-errorChannel: + ticker.Stop() + wg.Done() + return 0, err } } - return client.WaitForEvents() } -// FundChainlinkNodesAddress will fund all of the provided Chainlink nodes address at given index with a set amount of native currency -func FundChainlinkNodesAddress( - nodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, +var ContractDeploymentInterval = 200 + +// FundChainlinkNodesFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node +// from root private key. It returns an error if any of the transactions failed. +func FundChainlinkNodesFromRootAddress( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + amount *big.Float, +) error { + if len(client.PrivateKeys) == 0 { + return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) + } + + return FundChainlinkNodes(logger, client, nodes, client.PrivateKeys[0], amount) +} + +// FundChainlinkNodes sends native token amount (expressed in human-scale) to each Chainlink Node +// from private key's address. It returns an error if any of the transactions failed. +func FundChainlinkNodes( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, + amount *big.Float, +) error { + keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { + return cl.PrimaryEthAddress() + } + return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) +} + +// FundChainlinkNodesAtKeyIndexFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node +// from root private key.It returns an error if any of the transactions failed. It sends the funds to +// node address at keyIndex (as each node can have multiple addresses). +func FundChainlinkNodesAtKeyIndexFromRootAddress( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, amount *big.Float, keyIndex int, ) error { - for _, cl := range nodes { + if len(client.PrivateKeys) == 0 { + return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) + } + + return FundChainlinkNodesAtKeyIndex(logger, client, nodes, client.PrivateKeys[0], amount, keyIndex) +} + +// FundChainlinkNodesAtKeyIndex sends native token amount (expressed in human-scale) to each Chainlink Node +// from private key's address. It returns an error if any of the transactions failed. It sends the funds to +// node address at keyIndex (as each node can have multiple addresses). +func FundChainlinkNodesAtKeyIndex( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, + amount *big.Float, + keyIndex int, +) error { + keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { toAddress, err := cl.EthAddresses() if err != nil { - return err - } - toAddr := common.HexToAddress(toAddress[keyIndex]) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(toAddress[keyIndex], amount, gasEstimates) - if err != nil { - return err + return "", err } + return toAddress[keyIndex], nil } - return client.WaitForEvents() + return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) } -// FundChainlinkNodesAddress will fund all of the provided Chainlink nodes addresses with a set amount of native currency -func FundChainlinkNodesAddresses( - nodes []*client.ChainlinkClient, - client blockchain.EVMClient, +func fundChainlinkNodesAtAnyKey( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, amount *big.Float, + keyAddressFn func(contracts.ChainlinkNodeWithKeysAndAddress) (string, error), ) error { for _, cl := range nodes { - toAddress, err := cl.EthAddressesForChain(client.GetChainID().String()) + toAddress, err := keyAddressFn(cl) if err != nil { return err } - for _, addr := range toAddress { - toAddr := common.HexToAddress(addr) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(addr, amount, gasEstimates) - if err != nil { - return err - } - } - } - return client.WaitForEvents() -} -// FundChainlinkNodes will fund all of the provided Chainlink nodes with a set amount of native currency -func FundChainlinkNodesLink( - nodes []*client.ChainlinkK8sClient, - blockchain blockchain.EVMClient, - linkToken contracts.LinkToken, - linkAmount *big.Int, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() + fromAddress, err := privateKeyToAddress(privateKey) if err != nil { return err } - err = linkToken.Transfer(toAddress, linkAmount) + + receipt, err := SendFunds(logger, client, FundsToSendPayload{ + ToAddress: common.HexToAddress(toAddress), + Amount: conversions.EtherToWei(amount), + PrivateKey: privateKey, + }) if err != nil { + logger.Err(err). + Str("From", fromAddress.Hex()). + Str("To", toAddress). + Msg("Failed to fund Chainlink node") + return err } + + txHash := "(none)" + if receipt != nil { + txHash = receipt.TxHash.String() + } + + logger.Info(). + Str("From", fromAddress.Hex()). + Str("To", toAddress). + Str("TxHash", txHash). + Str("Amount", amount.String()). + Msg("Funded Chainlink node") } - return blockchain.WaitForEvents() + + return nil } -// ChainlinkNodeAddresses will return all the on-chain wallet addresses for a set of Chainlink nodes -func ChainlinkNodeAddresses(nodes []*client.ChainlinkK8sClient) ([]common.Address, error) { - addresses := make([]common.Address, 0) - for _, node := range nodes { - primaryAddress, err := node.PrimaryEthAddress() - if err != nil { - return nil, err +type FundsToSendPayload struct { + ToAddress common.Address + Amount *big.Int + PrivateKey *ecdsa.PrivateKey + GasLimit *int64 + GasPrice *big.Int + GasFeeCap *big.Int + GasTipCap *big.Int + TxTimeout *time.Duration +} + +// TODO: move to CTF? +// SendFunds sends native token amount (expressed in human-scale) from address controlled by private key +// to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap. +// Values that are not set will be estimated or taken from config. +func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) { + fromAddress, err := privateKeyToAddress(payload.PrivateKey) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithTimeout(context.Background(), client.Cfg.Network.TxnTimeout.Duration()) + nonce, err := client.Client.PendingNonceAt(ctx, fromAddress) + defer cancel() + if err != nil { + return nil, err + } + + var gasLimit int64 + gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) + if err != nil { + gasLimit = client.Cfg.Network.TransferGasFee + } else { + gasLimit = int64(gasLimitRaw) + } + + gasPrice := big.NewInt(0) + gasFeeCap := big.NewInt(0) + gasTipCap := big.NewInt(0) + + if payload.GasLimit != nil { + gasLimit = *payload.GasLimit + } + + if client.Cfg.Network.EIP1559DynamicFees { + // if any of the dynamic fees are not set, we need to either estimate them or read them from config + if payload.GasFeeCap == nil || payload.GasTipCap == nil { + // estimation or config reading happens here + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + gasFeeCap = txOptions.GasFeeCap + gasTipCap = txOptions.GasTipCap + } + + // override with payload values if they are set + if payload.GasFeeCap != nil { + gasFeeCap = payload.GasFeeCap + } + + if payload.GasTipCap != nil { + gasTipCap = payload.GasTipCap + } + } else { + if payload.GasPrice == nil { + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + gasPrice = txOptions.GasPrice + } else { + gasPrice = payload.GasPrice } - addresses = append(addresses, common.HexToAddress(primaryAddress)) } - return addresses, nil -} -// ChainlinkNodeAddressesAtIndex will return all the on-chain wallet addresses for a set of Chainlink nodes -func ChainlinkNodeAddressesAtIndex(nodes []*client.ChainlinkK8sClient, keyIndex int) ([]common.Address, error) { - addresses := make([]common.Address, 0) - for _, node := range nodes { - nodeAddresses, err := node.EthAddresses() - if err != nil { - return nil, err + var rawTx types.TxData + + if client.Cfg.Network.EIP1559DynamicFees { + rawTx = &types.DynamicFeeTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: uint64(gasLimit), + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + } + } else { + rawTx = &types.LegacyTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: uint64(gasLimit), + GasPrice: gasPrice, } - addresses = append(addresses, common.HexToAddress(nodeAddresses[keyIndex])) } - return addresses, nil -} -// SetChainlinkAPIPageSize specifies the page size from the Chainlink API, useful for high volume testing -func SetChainlinkAPIPageSize(nodes []*client.ChainlinkK8sClient, pageSize int) { - for _, n := range nodes { - n.SetPageSize(pageSize) + signedTx, err := types.SignNewTx(payload.PrivateKey, types.LatestSignerForChainID(big.NewInt(client.ChainID)), rawTx) + + if err != nil { + return nil, errors.Wrap(err, "failed to sign tx") + } + + txTimeout := client.Cfg.Network.TxnTimeout.Duration() + if payload.TxTimeout != nil { + txTimeout = *payload.TxTimeout + } + + logger.Debug(). + Str("From", fromAddress.Hex()). + Str("To", payload.ToAddress.Hex()). + Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). + Uint64("Nonce", nonce). + Int64("Gas Limit", gasLimit). + Str("Gas Price", gasPrice.String()). + Str("Gas Fee Cap", gasFeeCap.String()). + Str("Gas Tip Cap", gasTipCap.String()). + Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). + Msg("About to send funds") + + ctx, cancel = context.WithTimeout(ctx, txTimeout) + defer cancel() + err = client.Client.SendTransaction(ctx, signedTx) + if err != nil { + return nil, errors.Wrap(err, "failed to send transaction") + } + + logger.Debug(). + Str("From", fromAddress.Hex()). + Str("To", payload.ToAddress.Hex()). + Str("TxHash", signedTx.Hash().String()). + Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). + Uint64("Nonce", nonce). + Int64("Gas Limit", gasLimit). + Str("Gas Price", gasPrice.String()). + Str("Gas Fee Cap", gasFeeCap.String()). + Str("Gas Tip Cap", gasTipCap.String()). + Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). + Msg("Sent funds") + + receipt, receiptErr := client.WaitMined(ctx, logger, client.Client, signedTx) + if receiptErr != nil { + return nil, errors.Wrap(receiptErr, "failed to wait for transaction to be mined") + } + + if receipt.Status == 1 { + return receipt, nil } + + tx, _, err := client.Client.TransactionByHash(ctx, signedTx.Hash()) + if err != nil { + return nil, errors.Wrap(err, "failed to get transaction by hash ") + } + + _, err = client.Decode(tx, receiptErr) + if err != nil { + return nil, err + } + + return receipt, nil } -// ExtractRequestIDFromJobRun extracts RequestID from job runs response -func ExtractRequestIDFromJobRun(jobDecodeData client.RunsResponseData) ([]byte, error) { - var taskRun client.TaskRun - for _, tr := range jobDecodeData.Attributes.TaskRuns { - if tr.Type == "ethabidecodelog" { - taskRun = tr +// DeployForwarderContracts first deploys Operator Factory and then uses it to deploy given number of +// operator and forwarder pairs. It waits for each transaction to be mined and then extracts operator and +// forwarder addresses from emitted events. +func DeployForwarderContracts( + t *testing.T, + seth *seth.Client, + linkTokenAddress common.Address, + numberOfOperatorForwarderPairs int, +) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { + instance, err := contracts.DeployEthereumOperatorFactory(seth, linkTokenAddress) + require.NoError(t, err, "failed to create new instance of operator factory") + operatorFactoryInstance = &instance + + for i := 0; i < numberOfOperatorForwarderPairs; i++ { + decodedTx, err := seth.Decode(operatorFactoryInstance.DeployNewOperatorAndForwarder()) + require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") + + for i, event := range decodedTx.Events { + require.True(t, len(event.Topics) > 0, fmt.Sprintf("Event %d should have topics", i)) + switch event.Topics[0] { + case operator_factory.OperatorFactoryOperatorCreated{}.Topic().String(): + if address, ok := event.EventData["operator"]; ok { + operators = append(operators, address.(common.Address)) + } else { + require.Fail(t, "Operator address not found in event", event) + } + case operator_factory.OperatorFactoryAuthorizedForwarderCreated{}.Topic().String(): + if address, ok := event.EventData["forwarder"]; ok { + authorizedForwarders = append(authorizedForwarders, address.(common.Address)) + } else { + require.Fail(t, "Forwarder address not found in event", event) + } + } } } - var decodeLogTaskRun *client.DecodeLogTaskRun - if err := json.Unmarshal([]byte(taskRun.Output), &decodeLogTaskRun); err != nil { - return nil, err + return operators, authorizedForwarders, operatorFactoryInstance +} + +// WatchNewOCRRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new +// round from the contract, as this can cause some odd behavior in some cases. It announces success if latest round +// is >= roundNumber. +func WatchNewOCRRound( + l zerolog.Logger, + seth *seth.Client, + roundNumber int64, + ocrInstances []contracts.OffChainAggregatorWithRounds, + timeout time.Duration, +) error { + confirmed := make(map[string]bool) + timeoutC := time.After(timeout) + ticker := time.NewTicker(time.Millisecond * 200) + defer ticker.Stop() + + l.Info().Msgf("Waiting for round %d to be confirmed by all nodes", roundNumber) + + for { + select { + case <-timeoutC: + return fmt.Errorf("timeout waiting for round %d to be confirmed. %d/%d nodes confirmed it", roundNumber, len(confirmed), len(ocrInstances)) + case <-ticker.C: + for i := 0; i < len(ocrInstances); i++ { + if confirmed[ocrInstances[i].Address()] { + continue + } + ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) + roundData, err := ocrInstances[i].GetLatestRound(ctx) + if err != nil { + cancel() + return fmt.Errorf("getting latest round from OCR instance %d have failed: %w", i+1, err) + } + cancel() + if roundData.RoundId.Cmp(big.NewInt(roundNumber)) >= 0 { + l.Debug().Msgf("OCR instance %d/%d confirmed round %d", i+1, len(ocrInstances), roundNumber) + confirmed[ocrInstances[i].Address()] = true + } + } + if len(confirmed) == len(ocrInstances) { + return nil + } + } } - rqInts := decodeLogTaskRun.RequestID - return rqInts, nil } -// EncodeOnChainVRFProvingKey encodes uncompressed public VRF key to on-chain representation -func EncodeOnChainVRFProvingKey(vrfKey client.VRFKey) ([2]*big.Int, error) { - uncompressed := vrfKey.Data.Attributes.Uncompressed - provingKey := [2]*big.Int{} - var set1 bool - var set2 bool - // strip 0x to convert to int - provingKey[0], set1 = new(big.Int).SetString(uncompressed[2:66], 16) - if !set1 { - return [2]*big.Int{}, fmt.Errorf("can not convert VRF key to *big.Int") - } - provingKey[1], set2 = new(big.Int).SetString(uncompressed[66:], 16) - if !set2 { - return [2]*big.Int{}, fmt.Errorf("can not convert VRF key to *big.Int") +// AcceptAuthorizedReceiversOperator sets authorized receivers for each operator contract to +// authorizedForwarder and authorized EA to nodeAddresses. Once done, it confirms that authorizations +// were set correctly. +func AcceptAuthorizedReceiversOperator( + t *testing.T, + logger zerolog.Logger, + seth *seth.Client, + operator common.Address, + authorizedForwarder common.Address, + nodeAddresses []common.Address, +) { + operatorInstance, err := contracts.LoadEthereumOperator(logger, seth, operator) + require.NoError(t, err, "Loading operator contract shouldn't fail") + forwarderInstance, err := contracts.LoadEthereumAuthorizedForwarder(seth, authorizedForwarder) + require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") + + err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) + require.NoError(t, err, "Accepting authorized forwarder shouldn't fail") + + senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) + require.NoError(t, err, "Getting authorized senders shouldn't fail") + var nodesAddrs []string + for _, o := range nodeAddresses { + nodesAddrs = append(nodesAddrs, o.Hex()) } - return provingKey, nil + require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") + + owner, err := forwarderInstance.Owner(testcontext.Get(t)) + require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") + require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") } -// GetMockserverInitializerDataForOTPE creates mocked weiwatchers data needed for otpe -func GetMockserverInitializerDataForOTPE( - OCRInstances []contracts.OffchainAggregator, - chainlinkNodes []*client.ChainlinkK8sClient, -) (interface{}, error) { - var contractsInfo []ctfClient.ContractInfoJSON +// TrackForwarder creates forwarder track for a given Chainlink node +func TrackForwarder( + t *testing.T, + seth *seth.Client, + authorizedForwarder common.Address, + node contracts.ChainlinkNodeWithForwarder, +) { + l := logging.GetTestLogger(t) + chainID := big.NewInt(seth.ChainID) + _, _, err := node.TrackForwarder(chainID, authorizedForwarder) + require.NoError(t, err, "Forwarder track should be created") + l.Info().Str("NodeURL", node.GetConfig().URL). + Str("ForwarderAddress", authorizedForwarder.Hex()). + Str("ChaindID", chainID.String()). + Msg("Forwarder tracked") +} - for index, OCRInstance := range OCRInstances { - contractInfo := ctfClient.ContractInfoJSON{ - ContractVersion: 4, - Path: fmt.Sprintf("contract_%d", index), - Status: "live", - ContractAddress: OCRInstance.Address(), +// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults +func DeployOCRv2Contracts( + l zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenAddress common.Address, + transmitters []string, + ocrOptions contracts.OffchainOptions, +) ([]contracts.OffchainAggregatorV2, error) { + var ocrInstances []contracts.OffchainAggregatorV2 + for contractCount := 0; contractCount < numberOfContracts; contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregatorV2( + l, + seth, + linkTokenAddress, + ocrOptions, + ) + if err != nil { + return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) } - - contractsInfo = append(contractsInfo, contractInfo) } - contractsInitializer := ctfClient.HttpInitializer{ - Request: ctfClient.HttpRequest{Path: "/contracts.json"}, - Response: ctfClient.HttpResponse{Body: contractsInfo}, + // Gather address payees + var payees []string + for range transmitters { + payees = append(payees, seth.Addresses[0].Hex()) } - var nodesInfo []ctfClient.NodeInfoJSON - - for _, chainlink := range chainlinkNodes { - ocrKeys, err := chainlink.MustReadOCRKeys() + // Set Payees + for contractCount, ocrInstance := range ocrInstances { + err := ocrInstance.SetPayees(transmitters, payees) if err != nil { - return nil, err + return nil, fmt.Errorf("error settings OCR payees: %w", err) } - nodeInfo := ctfClient.NodeInfoJSON{ - NodeAddress: []string{ocrKeys.Data[0].Attributes.OnChainSigningAddress}, - ID: ocrKeys.Data[0].ID, + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) } - nodesInfo = append(nodesInfo, nodeInfo) } + return ocrInstances, nil +} - nodesInitializer := ctfClient.HttpInitializer{ - Request: ctfClient.HttpRequest{Path: "/nodes.json"}, - Response: ctfClient.HttpResponse{Body: nodesInfo}, +// ConfigureOCRv2AggregatorContracts sets configuration for a number of OCRv2 contracts +func ConfigureOCRv2AggregatorContracts( + contractConfig *contracts.OCRv2Config, + ocrv2Contracts []contracts.OffchainAggregatorV2, +) error { + for contractCount, ocrInstance := range ocrv2Contracts { + // Exclude the first node, which will be used as a bootstrapper + err := ocrInstance.SetConfig(contractConfig) + if err != nil { + return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } } - initializers := []ctfClient.HttpInitializer{contractsInitializer, nodesInitializer} - return initializers, nil + return nil } // TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the // specified path. Can also accept a testreporter (if one was used) to log further results func TeardownSuite( t *testing.T, + chainClient *seth.Client, env *environment.Environment, chainlinkNodes []*client.ChainlinkK8sClient, optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level grafnaUrlProvider testreporters.GrafanaURLProvider, - clients ...blockchain.EVMClient, ) error { l := logging.GetTestLogger(t) if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { @@ -285,61 +679,52 @@ func TeardownSuite( l.Warn().Msgf("Error deleting jobs %+v", err) } - for _, c := range clients { - if c != nil && chainlinkNodes != nil && len(chainlinkNodes) > 0 { - if err := ReturnFunds(chainlinkNodes, c); err != nil { - // This printed line is required for tests that use real funds to propagate the failure - // out to the system running the test. Do not remove - fmt.Println(environment.FAILED_FUND_RETURN) - l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - } else { - l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") - } - // nolint - if c != nil { - err := c.Close() - if err != nil { - return err - } + if chainlinkNodes != nil { + if err := ReturnFundsFromNodes(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { + // This printed line is required for tests that use real funds to propagate the failure + // out to the system running the test. Do not remove + fmt.Println(environment.FAILED_FUND_RETURN) + l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). + Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + + "Environment is left running so you can try manually!") } + } else { + l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") } return env.Shutdown() } -// TeardownRemoteSuite is used when running a test within a remote-test-runner, like for long-running performance and -// soak tests -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.TeardownRemoteSuite +// TeardownRemoteSuite sends a report and returns funds from chainlink nodes to network's default wallet func TeardownRemoteSuite( t *testing.T, + client *seth.Client, namespace string, chainlinkNodes []*client.ChainlinkK8sClient, optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics grafnaUrlProvider testreporters.GrafanaURLProvider, - client blockchain.EVMClient, ) error { l := logging.GetTestLogger(t) - var err error - if err = testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { + if err := testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { l.Warn().Err(err).Msg("Error writing test report") } // Delete all jobs to stop depleting the funds - err = DeleteAllJobs(chainlinkNodes) + err := DeleteAllJobs(chainlinkNodes) if err != nil { l.Warn().Msgf("Error deleting jobs %+v", err) } - if err = ReturnFunds(chainlinkNodes, client); err != nil { + if err = ReturnFundsFromNodes(l, client, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { l.Error().Err(err).Str("Namespace", namespace). Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + "Environment is left running so you can try manually!") } + return err } +// DeleteAllJobs deletes all jobs from all chainlink nodes +// added here temporarily to avoid circular import func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { for _, node := range chainlinkNodes { if node == nil { @@ -363,325 +748,421 @@ func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { return nil } -// ReturnFunds attempts to return all the funds from the chainlink nodes and other wallets to the network's default wallet, -// which will always be the first wallet in the list of wallets. If errors are encountered, it will keep trying other wallets -// and return all errors encountered. -func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error { - if blockchainClient == nil { - return fmt.Errorf("blockchain client is nil, unable to return funds from chainlink nodes") +// StartNewRound requests a new round from the ocr contracts and returns once transaction was mined +func StartNewRound( + ocrInstances []contracts.OffChainAggregatorWithRounds, +) error { + for i := 0; i < len(ocrInstances); i++ { + err := ocrInstances[i].RequestNewRound() + if err != nil { + return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) + } } - log.Info().Msg("Attempting to return Chainlink node funds to default network wallets") - if blockchainClient.NetworkSimulated() { - log.Info().Str("Network Name", blockchainClient.GetNetworkName()). - Msg("Network is a simulated network. Skipping fund return.") - return nil + return nil +} + +// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain +// aggregator contracts with forwarders as effectiveTransmitters +func DeployOCRContractsForwarderFlow( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, + forwarderAddresses []common.Address, +) ([]contracts.OffchainAggregator, error) { + transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { + transmitters = make([]string, 0) + payees = make([]string, 0) + for _, forwarderCommonAddress := range forwarderAddresses { + forwarderAddress := forwarderCommonAddress.Hex() + transmitters = append(transmitters, forwarderAddress) + payees = append(payees, seth.Addresses[0].Hex()) + } + + return } - // If we fail to return funds from some addresses, we still want to try to return funds from the rest - encounteredErrors := []error{} + transmitterAddressesFn := func() ([]common.Address, error) { + return forwarderAddresses, nil + } - if len(blockchainClient.GetWallets()) > 1 { - if err := blockchainClient.SetDefaultWallet(0); err != nil { - encounteredErrors = append(encounteredErrors, err) - } else { - for walletIndex := 1; walletIndex < len(blockchainClient.GetWallets()); walletIndex++ { - decodedKey, err := hex.DecodeString(blockchainClient.GetWallets()[walletIndex].PrivateKey()) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - privKey, err := crypto.ToECDSA(decodedKey) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } + return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) +} - err = blockchainClient.ReturnFunds(privKey) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } +// DeployOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts +func DeployOCRv1Contracts( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, +) ([]contracts.OffchainAggregator, error) { + transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { + transmitters = make([]string, 0) + payees = make([]string, 0) + for _, node := range workerNodes { + var addr string + addr, err = node.PrimaryEthAddress() + if err != nil { + err = fmt.Errorf("error getting node's primary ETH address: %w", err) + return } + transmitters = append(transmitters, addr) + payees = append(payees, seth.Addresses[0].Hex()) } + + return } - for _, chainlinkNode := range chainlinkNodes { - fundedKeys, err := chainlinkNode.ExportEVMKeysForChain(blockchainClient.GetChainID().String()) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - for _, key := range fundedKeys { - keyToDecrypt, err := json.Marshal(key) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM - // issues. So we avoid running in parallel; slower, but safer. - decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) + transmitterAddressesFn := func() ([]common.Address, error) { + transmitterAddresses := make([]common.Address, 0) + for _, node := range workerNodes { + primaryAddress, err := node.PrimaryEthAddress() if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - err = blockchainClient.ReturnFunds(decryptedKey.PrivateKey) - if err != nil { - encounteredErrors = append(encounteredErrors, fmt.Errorf("error returning funds from chainlink node: %w", err)) - continue + return nil, err } + transmitterAddresses = append(transmitterAddresses, common.HexToAddress(primaryAddress)) } + + return transmitterAddresses, nil } - if err := blockchainClient.WaitForEvents(); err != nil { - encounteredErrors = append(encounteredErrors, err) - } - if len(encounteredErrors) > 0 { - return fmt.Errorf("encountered errors while returning funds: %v", encounteredErrors) - } - return nil + + return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) } -// FundAddresses will fund a list of addresses with an amount of native currency -func FundAddresses(blockchain blockchain.EVMClient, amount *big.Float, addresses ...string) error { - for _, address := range addresses { - toAddr := common.HexToAddress(address) - gasEstimates, err := blockchain.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) +func deployAnyOCRv1Contracts( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, + getTransmitterAndPayeesFn func() ([]string, []string, error), + getTransmitterAddressesFn func() ([]common.Address, error), +) ([]contracts.OffchainAggregator, error) { + // Deploy contracts + var ocrInstances []contracts.OffchainAggregator + for contractCount := 0; contractCount < numberOfContracts; contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) if err != nil { - return err + return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) } - if err := blockchain.Fund(address, amount, gasEstimates); err != nil { - return err + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) } } - return blockchain.WaitForEvents() -} - -// EncodeOnChainExternalJobID encodes external job uuid to on-chain representation -func EncodeOnChainExternalJobID(jobID uuid.UUID) [32]byte { - var ji [32]byte - copy(ji[:], strings.Replace(jobID.String(), "-", "", 4)) - return ji -} -// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment -// to apply the upgrades -func UpgradeChainlinkNodeVersions( - testEnvironment *environment.Environment, - newImage, newVersion string, - nodes ...*client.ChainlinkK8sClient, -) error { - if newImage == "" || newVersion == "" { - return errors.New("New image and new version is needed to upgrade the node") + // Gather transmitter and address payees + var transmitters, payees []string + var err error + transmitters, payees, err = getTransmitterAndPayeesFn() + if err != nil { + return nil, fmt.Errorf("error getting transmitter and payees: %w", err) } - for _, node := range nodes { - if err := node.UpgradeVersion(testEnvironment, newImage, newVersion); err != nil { - return err + + // Set Payees + for contractCount, ocrInstance := range ocrInstances { + err := ocrInstance.SetPayees(transmitters, payees) + if err != nil { + return nil, fmt.Errorf("error settings OCR payees: %w", err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) } } - err := testEnvironment.RunUpdated(len(nodes)) - if err != nil { // Run the new environment and wait for changes to show - return err - } - return client.ReconnectChainlinkNodes(testEnvironment, nodes) -} -func DeployLINKToken(cd contracts.ContractDeployer) (contracts.LinkToken, error) { - linkToken, err := cd.DeployLinkTokenContract() + // Set Config + transmitterAddresses, err := getTransmitterAddressesFn() if err != nil { - return nil, err + return nil, fmt.Errorf("getting transmitter addresses should not fail: %w", err) } - return linkToken, err -} -func DeployMockETHLinkFeed(cd contracts.ContractDeployer, answer *big.Int) (contracts.MockETHLINKFeed, error) { - mockETHLINKFeed, err := cd.DeployMockETHLINKFeed(answer) - if err != nil { - return nil, err + for contractCount, ocrInstance := range ocrInstances { + // Exclude the first node, which will be used as a bootstrapper + err = ocrInstance.SetConfig( + workerNodes, + contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), + transmitterAddresses, + ) + if err != nil { + return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } } - return mockETHLINKFeed, err + + return ocrInstances, nil } -// todo - move to CTF -func GenerateWallet() (common.Address, error) { - privateKey, err := crypto.GenerateKey() - if err != nil { - return common.Address{}, err - } +func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { publicKey := privateKey.Public() publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) if !ok { - return common.Address{}, fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey") + return common.Address{}, errors.New("error casting public key to ECDSA") } return crypto.PubkeyToAddress(*publicKeyECDSA), nil } -// todo - move to CTF -func GetTxFromAddress(tx *types.Transaction) (string, error) { - from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) - return from.String(), err -} +func WatchNewFluxRound( + l zerolog.Logger, + seth *seth.Client, + roundNumber int64, + fluxInstance contracts.FluxAggregator, + timeout time.Duration, +) error { + timeoutC := time.After(timeout) + ticker := time.NewTicker(time.Millisecond * 200) + defer ticker.Stop() -// todo - move to CTF -func DecodeTxInputData(abiString string, data []byte) (map[string]interface{}, error) { - jsonABI, err := abi.JSON(strings.NewReader(abiString)) - if err != nil { - return nil, err - } - methodSigData := data[:4] - inputsSigData := data[4:] - method, err := jsonABI.MethodById(methodSigData) - if err != nil { - return nil, err - } - inputsMap := make(map[string]interface{}) - if err := method.Inputs.UnpackIntoMap(inputsMap, inputsSigData); err != nil { - return nil, err - } - return inputsMap, nil -} + l.Info().Msgf("Waiting for flux round %d to be confirmed by flux aggregator", roundNumber) -// todo - move to CTF -func WaitForBlockNumberToBe( - waitForBlockNumberToBe uint64, - client *seth.Client, - wg *sync.WaitGroup, - timeout time.Duration, - t testing.TB, - l zerolog.Logger, -) (uint64, error) { - blockNumberChannel := make(chan uint64) - errorChannel := make(chan error) - testContext, testCancel := context.WithTimeout(context.Background(), timeout) - defer testCancel() - ticker := time.NewTicker(time.Second * 5) - var latestBlockNumber uint64 for { select { - case <-testContext.Done(): - ticker.Stop() - wg.Done() - return latestBlockNumber, - fmt.Errorf("timeout waiting for Block Number to be: %d. Last recorded block number was: %d", - waitForBlockNumberToBe, latestBlockNumber) + case <-timeoutC: + return fmt.Errorf("timeout waiting for round %d to be confirmed", roundNumber) case <-ticker.C: - go func() { - currentBlockNumber, err := client.Client.BlockNumber(testcontext.Get(t)) - if err != nil { - errorChannel <- err - } - l.Info(). - Uint64("Latest Block Number", currentBlockNumber). - Uint64("Desired Block Number", waitForBlockNumberToBe). - Msg("Waiting for Block Number to be") - blockNumberChannel <- currentBlockNumber - }() - case latestBlockNumber = <-blockNumberChannel: - if latestBlockNumber >= waitForBlockNumberToBe { - ticker.Stop() - wg.Done() - l.Info(). - Uint64("Latest Block Number", latestBlockNumber). - Uint64("Desired Block Number", waitForBlockNumberToBe). - Msg("Desired Block Number reached!") - return latestBlockNumber, nil + ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) + roundId, err := fluxInstance.LatestRoundID(ctx) + if err != nil { + cancel() + return fmt.Errorf("getting latest round from flux instance has failed: %w", err) + } + cancel() + if roundId.Cmp(big.NewInt(roundNumber)) >= 0 { + l.Debug().Msgf("Flux instance confirmed round %d", roundNumber) + return nil } - case err := <-errorChannel: - ticker.Stop() - wg.Done() - return 0, err } } } -// todo - move to EVMClient -func RewindSimulatedChainToBlockNumber( - ctx context.Context, - client *seth.Client, - rpcURL string, - rewindChainToBlockNumber uint64, - l zerolog.Logger, -) (uint64, error) { - latestBlockNumberBeforeReorg, err := client.Client.BlockNumber(ctx) - if err != nil { - return 0, fmt.Errorf("error getting latest block number: %w", err) +// EstimateCostForChainlinkOperations estimates the cost of running a number of operations on the Chainlink node based on estimated gas costs. It supports +// both legacy and EIP-1559 transactions. +func EstimateCostForChainlinkOperations(l zerolog.Logger, client *seth.Client, network blockchain.EVMNetwork, amountOfOperations int) (*big.Float, error) { + bigAmountOfOperations := big.NewInt(int64(amountOfOperations)) + estimations := client.CalculateGasEstimations(client.NewDefaultGasEstimationRequest()) + + gasLimit := network.GasEstimationBuffer + network.ChainlinkTransactionLimit + + var gasPriceInWei *big.Int + if client.Cfg.Network.EIP1559DynamicFees { + gasPriceInWei = estimations.GasFeeCap + } else { + gasPriceInWei = estimations.GasPrice } - l.Info(). - Str("RPC URL", rpcURL). - Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). - Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). - Msg("Performing Reorg on chain by rewinding chain to specific block number") + gasCostPerOperationWei := big.NewInt(1).Mul(big.NewInt(1).SetUint64(gasLimit), gasPriceInWei) + gasCostPerOperationETH := conversions.WeiToEther(gasCostPerOperationWei) + // total Wei needed for all TXs = total value for TX * number of TXs + totalWeiForAllOperations := big.NewInt(1).Mul(gasCostPerOperationWei, bigAmountOfOperations) + totalEthForAllOperations := conversions.WeiToEther(totalWeiForAllOperations) - _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + l.Debug(). + Int("Number of Operations", amountOfOperations). + Uint64("Gas Limit per Operation", gasLimit). + Str("Value per Operation (ETH)", gasCostPerOperationETH.String()). + Str("Total (ETH)", totalEthForAllOperations.String()). + Msg("Calculated ETH for Chainlink Operations") + return totalEthForAllOperations, nil +} + +// GetLatestFinalizedBlockHeader returns latest finalised block header for given network (taking into account finality tag/depth) +func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, network blockchain.EVMNetwork) (*types.Header, error) { + if network.FinalityTag { + return client.Client.HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64())) + } + if network.FinalityDepth == 0 { + return nil, fmt.Errorf("finality depth is 0 and finality tag is not enabled") + } + header, err := client.Client.HeaderByNumber(ctx, nil) if err != nil { - return 0, fmt.Errorf("error making reorg: %w", err) + return nil, err } + latestBlockNumber := header.Number.Uint64() + finalizedBlockNumber := latestBlockNumber - network.FinalityDepth + return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) +} - latestBlockNumberAfterReorg, err := client.Client.BlockNumber(ctx) - if err != nil { - return 0, fmt.Errorf("error getting latest block number: %w", err) +// SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses +// Multicall contract to batch all transfers in a single transaction. It also checks if the funds were transferred correctly. +// It's primary use case is to fund addresses that will be used for Upkeep registration (as that requires LINK balance) during +// Automation/Keeper test setup. +func SendLinkFundsToDeploymentAddresses( + chainClient *seth.Client, + concurrency, + totalUpkeeps, + operationsPerAddress int, + multicallAddress common.Address, + linkAmountPerUpkeep *big.Int, + linkToken contracts.LinkToken, +) error { + var generateCallData = func(receiver common.Address, amount *big.Int) ([]byte, error) { + abi, err := link_token_interface.LinkTokenMetaData.GetAbi() + if err != nil { + return nil, err + } + data, err := abi.Pack("transfer", receiver, amount) + if err != nil { + return nil, err + } + return data, nil } - l.Info(). - Uint64("Block Number", latestBlockNumberAfterReorg). - Msg("Latest Block Number after Reorg") - return latestBlockNumberAfterReorg, nil -} + toTransferToMultiCallContract := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(totalUpkeeps+concurrency))) + toTransferPerClient := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(operationsPerAddress+1))) + err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) + if err != nil { + return errors.Wrapf(err, "Error transferring LINK to multicall contract") + } -func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { - provider, err := env.GetRpcProvider(chainID) + balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) if err != nil { - return "", err + return errors.Wrapf(err, "Error getting LINK balance of multicall contract") } - return provider.PublicHttpUrls()[0], nil -} -// RPCRawClient -// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" -type RPCRawClient struct { - resty *resty.Client -} + if balance.Cmp(toTransferToMultiCallContract) < 0 { + return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), balance.String()) + } -func NewRPCRawClient(url string) *RPCRawClient { - isDebug := os.Getenv("DEBUG_RESTY") == "true" - restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) - return &RPCRawClient{ - resty: restyClient, + // Transfer LINK to ephemeral keys + multiCallData := make([][]byte, 0) + for i := 1; i <= concurrency; i++ { + data, err := generateCallData(chainClient.Addresses[i], toTransferPerClient) + if err != nil { + return errors.Wrapf(err, "Error generating call data for LINK transfer") + } + multiCallData = append(multiCallData, data) } -} -func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { - var responseObject JsonRPCResponse - postBody, _ := json.Marshal(map[string]any{ - "jsonrpc": "2.0", - "id": 1, - "method": "debug_setHead", - "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, - }) - resp, err := g.resty.R(). - SetHeader("Content-Type", "application/json"). - SetBody(postBody). - SetResult(&responseObject). - Post("") + var call []contracts.Call + for _, d := range multiCallData { + data := contracts.Call{Target: common.HexToAddress(linkToken.Address()), AllowFailure: false, CallData: d} + call = append(call, data) + } + multiCallABI, err := abi.JSON(strings.NewReader(contracts.MultiCallABI)) + if err != nil { + return errors.Wrapf(err, "Error getting Multicall contract ABI") + } + boundContract := bind.NewBoundContract(multicallAddress, multiCallABI, chainClient.Client, chainClient.Client, chainClient.Client) + // call aggregate3 to group all msg call data and send them in a single transaction + _, err = chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) if err != nil { - return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + return errors.Wrapf(err, "Error calling Multicall contract") + } + + for i := 1; i <= concurrency; i++ { + balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) + if err != nil { + return errors.Wrapf(err, "Error getting LINK balance of ephemeral key %d", i) + } + if balance.Cmp(toTransferPerClient) < 0 { + return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), balance.String()) + } + } + + return nil +} + +// GenerateUpkeepReport generates a report of performed, successful, reverted and stale upkeeps for a given registry contract based on transaction logs. In case of test failure it can help us +// to triage the issue by providing more context. +func GenerateUpkeepReport(t *testing.T, chainClient *seth.Client, startBlock, endBlock *big.Int, instance contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) (performedUpkeeps, successfulUpkeeps, revertedUpkeeps, staleUpkeeps int, err error) { + registryLogs := []gethtypes.Log{} + l := logging.GetTestLogger(t) + + var ( + blockBatchSize int64 = 100 + logs []gethtypes.Log + timeout = 5 * time.Second + addr = common.HexToAddress(instance.Address()) + queryStartBlock = startBlock + ) + + // Gather logs from the registry in 100 block chunks to avoid read limits + for queryStartBlock.Cmp(endBlock) < 0 { + filterQuery := geth.FilterQuery{ + Addresses: []common.Address{addr}, + FromBlock: queryStartBlock, + ToBlock: big.NewInt(0).Add(queryStartBlock, big.NewInt(blockBatchSize)), + } + + // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats. + err = fmt.Errorf("initial error") // to ensure our for loop runs at least once + for err != nil { + ctx, cancel := context.WithTimeout(testcontext.Get(t), timeout) + logs, err = chainClient.Client.FilterLogs(ctx, filterQuery) + cancel() + if err != nil { + l.Error(). + Err(err). + Interface("Filter Query", filterQuery). + Str("Timeout", timeout.String()). + Msg("Error getting logs from chain, trying again") + timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) + continue + } + l.Info(). + Uint64("From Block", queryStartBlock.Uint64()). + Uint64("To Block", filterQuery.ToBlock.Uint64()). + Int("Log Count", len(logs)). + Str("Registry Address", addr.Hex()). + Msg("Collected logs") + queryStartBlock.Add(queryStartBlock, big.NewInt(blockBatchSize)) + registryLogs = append(registryLogs, logs...) + } } - statusCode := resp.StatusCode() - if statusCode != 200 && statusCode != 201 { - return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + + var contractABI *abi.ABI + contractABI, err = contracts.GetRegistryContractABI(registryVersion) + if err != nil { + return } - if responseObject.Error != "" { - return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + + for _, allLogs := range registryLogs { + log := allLogs + var eventDetails *abi.Event + eventDetails, err = contractABI.EventByID(log.Topics[0]) + if err != nil { + l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error getting event details for log, report data inaccurate") + break + } + if eventDetails.Name == "UpkeepPerformed" { + performedUpkeeps++ + var parsedLog *contracts.UpkeepPerformedLog + parsedLog, err = instance.ParseUpkeepPerformedLog(&log) + if err != nil { + l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error parsing upkeep performed log, report data inaccurate") + break + } + if !parsedLog.Success { + revertedUpkeeps++ + } else { + successfulUpkeeps++ + } + } else if eventDetails.Name == "StaleUpkeepReport" { + staleUpkeeps++ + } } - return responseObject, nil + + return } -type JsonRPCResponse struct { - Version string `json:"jsonrpc"` - Id int `json:"id"` - Result string `json:"result,omitempty"` - Error string `json:"error,omitempty"` +func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClient *seth.Client, startBlock uint64, registry contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) func() { + return func() { + if t.Failed() { + endBlock, err := chainClient.Client.BlockNumber(context.Background()) + require.NoError(t, err, "Failed to get end block") + + total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) + require.NoError(t, err, "Failed to get staleness data") + if stale > 0 || reverted > 0 { + logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") + } else { + logger.Info().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") + } + } + } } diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go deleted file mode 100644 index 5bb0c202a55..00000000000 --- a/integration-tests/actions/actions_local.go +++ /dev/null @@ -1,18 +0,0 @@ -// Package actions enables common chainlink interactions -package actions - -import "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - -// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment -// to apply the upgrades -func UpgradeChainlinkNodeVersionsLocal( - newImage, newVersion string, - nodes ...*test_env.ClNode, -) error { - for _, node := range nodes { - if err := node.UpgradeVersion(newImage, newVersion); err != nil { - return err - } - } - return nil -} diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 9ee14d4a6a1..22220af9d63 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -9,6 +9,9 @@ import ( "testing" "time" + "github.com/pkg/errors" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" "github.com/stretchr/testify/require" @@ -20,7 +23,6 @@ import ( ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -259,37 +261,44 @@ func CreateOCRKeeperJobs( // DeployAutoOCRRegistryAndRegistrar registry and registrar func DeployAutoOCRRegistryAndRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registrySettings contracts.KeeperRegistrySettings, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar) { - registry := deployRegistry(t, registryVersion, registrySettings, contractDeployer, client, linkToken) - registrar := deployRegistrar(t, registryVersion, registry, linkToken, contractDeployer, client) + registry := deployRegistry(t, client, registryVersion, registrySettings, linkToken) + registrar := deployRegistrar(t, client, registryVersion, registry, linkToken) return registry, registrar } -func DeployConsumers(t *testing.T, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, isLogTrigger, isMercury) +// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. +func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + + upkeeps := DeployKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury) + require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } upkeepIds := RegisterUpkeepContracts( - t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, + t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, ) + require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") return upkeeps, upkeepIds } +// DeployPerformanceConsumers deploys and registers keeper performance consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkeep will be registered with root key address as the admin. +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. func DeployPerformanceConsumers( t *testing.T, + chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, @@ -299,44 +308,74 @@ func DeployPerformanceConsumers( performGasToBurn int64, // How much gas should be burned on performUpkeep() calls ) ([]contracts.KeeperConsumerPerformance, []*big.Int) { upkeeps := DeployKeeperConsumersPerformance( - t, contractDeployer, client, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, + t, chainClient, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, ) + + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) return upkeeps, upkeepIds } +// DeployPerformDataCheckerConsumers deploys and registers keeper performance data checkers consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deployes multicall contract and sends link funds to each deployment address. func DeployPerformDataCheckerConsumers( t *testing.T, + chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, expectedData []byte, ) ([]contracts.KeeperPerformDataChecker, []*big.Int) { - upkeeps := DeployPerformDataChecker(t, contractDeployer, client, numberOfUpkeeps, expectedData) + upkeeps := DeployPerformDataChecker(t, chainClient, numberOfUpkeeps, expectedData) + + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) return upkeeps, upkeepIds } +// DeployMultiCallAndFundDeploymentAddresses deploys multicall contract and sends link funds to each deployment address +func DeployMultiCallAndFundDeploymentAddresses( + chainClient *seth.Client, + linkToken contracts.LinkToken, + numberOfUpkeeps int, + linkFundsForEachUpkeep *big.Int, +) error { + concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) + if err != nil { + return err + } + + operationsPerAddress := numberOfUpkeeps / concurrency + + multicallAddress, err := contracts.DeployMultiCallContract(chainClient) + if err != nil { + return errors.Wrap(err, "Error deploying multicall contract") + } + + return SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) +} + func deployRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registry contracts.KeeperRegistry, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, ) contracts.KeeperRegistrar { registrarSettings := contracts.KeeperRegistrarSettings{ AutoApproveConfigType: 2, @@ -344,31 +383,29 @@ func deployRegistrar( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar, err := contractDeployer.DeployKeeperRegistrar(registryVersion, linkToken.Address(), registrarSettings) + registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for registrar to deploy") return registrar } func deployRegistry( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registrySettings contracts.KeeperRegistrySettings, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, linkToken contracts.LinkToken, ) contracts.KeeperRegistry { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") // Deploy the transcoder here, and then set it to the registry - transcoder := DeployUpkeepTranscoder(t, contractDeployer, client) - registry := DeployKeeperRegistry(t, contractDeployer, client, + transcoder, err := contracts.DeployUpkeepTranscoder(client) + require.NoError(t, err, "Deploying upkeep transcoder shouldn't fail") + + registry, err := contracts.DeployKeeperRegistry( + client, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -379,5 +416,6 @@ func deployRegistry( Settings: registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry contract shouldn't fail") return registry } diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 25e6a4a7a06..ced41dfb427 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -28,7 +28,7 @@ import ( ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" @@ -590,7 +590,7 @@ func (r registrationResult) GetResult() common.Hash { } func (a *AutomationTest) RegisterUpkeeps(upkeepConfigs []UpkeepConfig, maxConcurrency int) ([]common.Hash, error) { - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(a.ChainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(a.ChainClient, 1) if err != nil { return nil, err } @@ -691,7 +691,7 @@ func (c confirmationResult) GetResult() UpkeepId { } func (a *AutomationTest) ConfirmUpkeepsRegistered(registrationTxHashes []common.Hash, maxConcurrency int) ([]*big.Int, error) { - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(a.ChainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(a.ChainClient, 1) if err != nil { return nil, err } diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 950d14ac8ea..882544e858a 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -1,62 +1,30 @@ package actions import ( + "context" "fmt" "math" "math/big" "strconv" "testing" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/google/uuid" + "github.com/pkg/errors" + "github.com/smartcontractkit/seth" + + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) var ZeroAddress = common.Address{} -func CreateKeeperJobs( - t *testing.T, - chainlinkNodes []*client.ChainlinkK8sClient, - keeperRegistry contracts.KeeperRegistry, - ocrConfig contracts.OCRv2Config, - evmChainID string, -) { - // Send keeper jobs to registry and chainlink nodes - primaryNode := chainlinkNodes[0] - primaryNodeAddress, err := primaryNode.PrimaryEthAddress() - require.NoError(t, err, "Reading ETH Keys from Chainlink Client shouldn't fail") - nodeAddresses, err := ChainlinkNodeAddresses(chainlinkNodes) - require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - nodeAddressesStr, payees := make([]string, 0), make([]string, 0) - for _, cla := range nodeAddresses { - nodeAddressesStr = append(nodeAddressesStr, cla.Hex()) - payees = append(payees, primaryNodeAddress) - } - err = keeperRegistry.SetKeepers(nodeAddressesStr, payees, ocrConfig) - require.NoError(t, err, "Setting keepers in the registry shouldn't fail") - - for _, chainlinkNode := range chainlinkNodes { - chainlinkNodeAddress, err := chainlinkNode.PrimaryEthAddress() - require.NoError(t, err, "Error retrieving chainlink node address") - _, err = chainlinkNode.MustCreateJob(&client.KeeperJobSpec{ - Name: fmt.Sprintf("keeper-test-%s", keeperRegistry.Address()), - ContractAddress: keeperRegistry.Address(), - FromAddress: chainlinkNodeAddress, - EVMChainID: evmChainID, - MinIncomingConfirmations: 1, - }) - require.NoError(t, err, "Creating KeeperV2 Job shouldn't fail") - } -} - func CreateKeeperJobsWithKeyIndex( t *testing.T, chainlinkNodes []*client.ChainlinkK8sClient, @@ -109,20 +77,20 @@ func DeployKeeperContracts( numberOfUpkeeps int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, linkFundsForEachUpkeep *big.Int, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumer, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") // Deploy the transcoder here, and then set it to the registry - transcoder := DeployUpkeepTranscoder(t, contractDeployer, client) - registry := DeployKeeperRegistry(t, contractDeployer, client, + transcoder, err := contracts.DeployUpkeepTranscoder(client) + require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") + + registry, err := contracts.DeployKeeperRegistry( + client, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -133,6 +101,7 @@ func DeployKeeperContracts( Settings: registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) @@ -144,16 +113,9 @@ func DeployKeeperContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, false, false) - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for events") + registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) + upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false) return registry, registrar, upkeeps, upkeepIds } @@ -161,12 +123,11 @@ func DeployKeeperContracts( // DeployPerformanceKeeperContracts deploys a set amount of keeper performance contracts registered to a single registry func DeployPerformanceKeeperContracts( t *testing.T, + chainClient *seth.Client, registryVersion ethereum.KeeperRegistryVersion, numberOfContracts int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registrySettings *contracts.KeeperRegistrySettings, linkFundsForEachUpkeep *big.Int, blockRange, // How many blocks to run the test for @@ -174,14 +135,13 @@ func DeployPerformanceKeeperContracts( checkGasToBurn, // How much gas should be burned on checkUpkeep() calls performGasToBurn int64, // How much gas should be burned on performUpkeep() calls ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumerPerformance, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") - registry := DeployKeeperRegistry(t, contractDeployer, client, + registry, err := contracts.DeployKeeperRegistry( + chainClient, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -192,6 +152,7 @@ func DeployPerformanceKeeperContracts( Settings: *registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) @@ -203,10 +164,13 @@ func DeployPerformanceKeeperContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) + registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) + + err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") upkeeps := DeployKeeperConsumersPerformance( - t, contractDeployer, client, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, + t, chainClient, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, ) var upkeepsAddresses []string @@ -214,7 +178,7 @@ func DeployPerformanceKeeperContracts( upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) return registry, registrar, upkeeps, upkeepIds } @@ -222,24 +186,22 @@ func DeployPerformanceKeeperContracts( // DeployPerformDataCheckerContracts deploys a set amount of keeper perform data checker contracts registered to a single registry func DeployPerformDataCheckerContracts( t *testing.T, + chainClient *seth.Client, registryVersion ethereum.KeeperRegistryVersion, numberOfContracts int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registrySettings *contracts.KeeperRegistrySettings, linkFundsForEachUpkeep *big.Int, expectedData []byte, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperPerformDataChecker, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") - registry := DeployKeeperRegistry(t, contractDeployer, client, + registry, err := contracts.DeployKeeperRegistry( + chainClient, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -250,6 +212,7 @@ func DeployPerformDataCheckerContracts( Settings: *registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) @@ -261,124 +224,126 @@ func DeployPerformDataCheckerContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) - upkeeps := DeployPerformDataChecker(t, contractDeployer, client, numberOfContracts, expectedData) + registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) + upkeeps := DeployPerformDataChecker(t, chainClient, numberOfContracts, expectedData) + + err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) return registry, registrar, upkeeps, upkeepIds } -func DeployKeeperRegistry( - t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, - registryOpts *contracts.KeeperRegistryOpts, -) contracts.KeeperRegistry { - registry, err := contractDeployer.DeployKeeperRegistry( - registryOpts, - ) - require.NoError(t, err, "Deploying keeper registry shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for keeper registry to deploy") - - return registry -} - func DeployKeeperRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, linkToken contracts.LinkToken, registrarSettings contracts.KeeperRegistrarSettings, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registry contracts.KeeperRegistry, ) contracts.KeeperRegistrar { - registrar, err := contractDeployer.DeployKeeperRegistrar(registryVersion, linkToken.Address(), registrarSettings) - - require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - err = client.WaitForEvents() + registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) require.NoError(t, err, "Failed waiting for registrar to deploy") if registryVersion != ethereum.RegistryVersion_2_0 { err = registry.SetRegistrar(registrar.Address()) require.NoError(t, err, "Registering the registrar address on the registry shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for registry to set registrar") } return registrar } -func DeployUpkeepTranscoder( - t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, -) contracts.UpkeepTranscoder { - transcoder, err := contractDeployer.DeployUpkeepTranscoder() - require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for transcoder to deploy") - - return transcoder -} - -func RegisterUpkeepContracts(t *testing.T, linkToken contracts.LinkToken, linkFunds *big.Int, client blockchain.EVMClient, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { +func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { checkData := make([][]byte, 0) for i := 0; i < numberOfContracts; i++ { checkData = append(checkData, []byte("0")) } return RegisterUpkeepContractsWithCheckData( - t, linkToken, linkFunds, client, upkeepGasLimit, registry, registrar, + t, client, linkToken, linkFunds, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury) } -func RegisterUpkeepContractsWithCheckData(t *testing.T, linkToken contracts.LinkToken, linkFunds *big.Int, client blockchain.EVMClient, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { +type upkeepRegistrationResult struct { + upkeepID UpkeepId +} + +func (r upkeepRegistrationResult) GetResult() *big.Int { + return r.upkeepID +} + +type upkeepConfig struct { + address string + data []byte +} + +type UpkeepId = *big.Int + +func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { l := logging.GetTestLogger(t) - registrationTxHashes := make([]common.Hash, 0) - upkeepIds := make([]*big.Int, 0) - for contractCount, upkeepAddress := range upkeepAddresses { + + concurrency, err := GetAndAssertCorrectConcurrency(client, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + executor := ctf_concurrency.NewConcurrentExecutor[UpkeepId, upkeepRegistrationResult, upkeepConfig](l) + + configs := make([]upkeepConfig, 0) + for i := 0; i < len(upkeepAddresses); i++ { + configs = append(configs, upkeepConfig{address: upkeepAddresses[i], data: checkData[i]}) + } + + var registerUpkeepFn = func(resultCh chan upkeepRegistrationResult, errorCh chan error, executorNum int, config upkeepConfig) { + id := uuid.New().String() + keyNum := executorNum + 1 // key 0 is the root key + req, err := registrar.EncodeRegisterRequest( - fmt.Sprintf("upkeep_%d", contractCount+1), + fmt.Sprintf("upkeep_%s", id), []byte("test@mail.com"), - upkeepAddress, + config.address, upkeepGasLimit, - client.GetDefaultWallet().Address(), // upkeep Admin - checkData[contractCount], + client.MustGetRootKeyAddress().Hex(), // upkeep Admin + config.data, linkFunds, 0, - client.GetDefaultWallet().Address(), + client.Addresses[keyNum].Hex(), isLogTrigger, isMercury, ) - require.NoError(t, err, "Encoding the register request shouldn't fail") - tx, err := linkToken.TransferAndCall(registrar.Address(), linkFunds, req) - require.NoError(t, err, "Error registering the upkeep consumer to the registrar") - l.Debug(). - Str("Contract Address", upkeepAddress). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Str("TxHash", tx.Hash().String()). - Str("Check Data", hexutil.Encode(checkData[contractCount])). - Msg("Registered Keeper Consumer Contract") - registrationTxHashes = append(registrationTxHashes, tx.Hash()) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait after registering upkeep consumers") + + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to encode register request for upkeep at %s", id, config.address) + return + } + + balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s]Failed to get LINK balance of %s", id, client.Addresses[keyNum].Hex()) + return + } + + // not stricly necessary, but helps us to avoid an errorless revert if there is not enough LINK + if balance.Cmp(linkFunds) < 0 { + errorCh <- fmt.Errorf("[id: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", id, client.Addresses[keyNum].Hex(), balance.String(), linkFunds.String()) + return + } + + tx, err := linkToken.TransferAndCallFromKey(registrar.Address(), linkFunds, req, keyNum) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to register upkeep at %s", id, config.address) + return + } + + receipt, err := client.Client.TransactionReceipt(context.Background(), tx.Hash()) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to get receipt for upkeep at %s and tx hash %s", id, config.address, tx.Hash()) + return } - } - err := client.WaitForEvents() - require.NoError(t, err, "Failed while waiting for all consumer contracts to be registered to registrar") - // Fetch the upkeep IDs - for _, txHash := range registrationTxHashes { - receipt, err := client.GetTxReceipt(txHash) - require.NoError(t, err, "Registration tx should be completed") var upkeepId *big.Int for _, rawLog := range receipt.Logs { parsedUpkeepId, err := registry.ParseUpkeepIdFromRegisteredLog(rawLog) @@ -387,63 +352,87 @@ func RegisterUpkeepContractsWithCheckData(t *testing.T, linkToken contracts.Link break } } - require.NotNil(t, upkeepId, "Upkeep ID should be found after registration") + + if upkeepId == nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed find upkeep ID for upkeep at %s in logs of tx with hash %s", id, config.address, tx.Hash()) + return + } + l.Debug(). - Str("TxHash", txHash.String()). + Str("TxHash", tx.Hash().String()). Str("Upkeep ID", upkeepId.String()). Msg("Found upkeepId in tx hash") - upkeepIds = append(upkeepIds, upkeepId) + + resultCh <- upkeepRegistrationResult{upkeepID: upkeepId} } + + upkeepIds, err := executor.Execute(concurrency, configs, registerUpkeepFn) + require.NoError(t, err, "Failed to register upkeeps using executor") + + require.Equal(t, numberOfContracts, len(upkeepIds), "Incorrect number of Keeper Consumer Contracts registered") l.Info().Msg("Successfully registered all Keeper Consumer Contracts") + return upkeepIds } -func DeployKeeperConsumers(t *testing.T, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { +type keeperConsumerResult struct { + contract contracts.KeeperConsumer +} + +func (k keeperConsumerResult) GetResult() contracts.KeeperConsumer { + return k.contract +} + +// DeployKeeperConsumers concurrently deploys keeper consumer contracts. It requires at least 1 ephemeral key to be present in Seth config. +func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { l := logging.GetTestLogger(t) - keeperConsumerContracts := make([]contracts.KeeperConsumer, 0) - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer + concurrency, err := GetAndAssertCorrectConcurrency(client, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + executor := ctf_concurrency.NewConcurrentExecutor[contracts.KeeperConsumer, keeperConsumerResult, ctf_concurrency.NoTaskType](l) + + var deployContractFn = func(channel chan keeperConsumerResult, errorCh chan error, executorNum int) { + keyNum := executorNum + 1 // key 0 is the root key var keeperConsumerInstance contracts.KeeperConsumer var err error if isMercury && isLogTrigger { // v2.1 only: Log triggered based contract with Mercury enabled - keeperConsumerInstance, err = contractDeployer.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() + keeperConsumerInstance, err = contracts.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumerFromKey(client, keyNum) } else if isMercury { // v2.1 only: Conditional based contract with Mercury enabled - keeperConsumerInstance, err = contractDeployer.DeployAutomationStreamsLookupUpkeepConsumer(big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range + keeperConsumerInstance, err = contracts.DeployAutomationStreamsLookupUpkeepConsumerFromKey(client, keyNum, big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range } else if isLogTrigger { // v2.1 only: Log triggered based contract without Mercury - keeperConsumerInstance, err = contractDeployer.DeployAutomationLogTriggerConsumer(big.NewInt(1000)) // 1000 block test range + keeperConsumerInstance, err = contracts.DeployAutomationLogTriggerConsumerFromKey(client, keyNum, big.NewInt(1000)) // 1000 block test range } else { // v2.0 and v2.1: Conditional based contract without Mercury - keeperConsumerInstance, err = contractDeployer.DeployUpkeepCounter(big.NewInt(999999), big.NewInt(5)) + keeperConsumerInstance, err = contracts.DeployUpkeepCounterFromKey(client, keyNum, big.NewInt(999999), big.NewInt(5)) } - require.NoError(t, err, "Deploying Consumer instance %d shouldn't fail", contractCount+1) - keeperConsumerContracts = append(keeperConsumerContracts, keeperConsumerInstance) - l.Debug(). - Str("Contract Address", keeperConsumerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err := client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") + if err != nil { + errorCh <- errors.Wrapf(err, "Failed to deploy keeper consumer contract") + return } + + channel <- keeperConsumerResult{contract: keeperConsumerInstance} } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + + results, err := executor.ExecuteSimple(concurrency, numberOfContracts, deployContractFn) + require.NoError(t, err, "Failed to deploy keeper consumers") + + // require.Equal(t, 0, len(deplymentErrors), "Error deploying consumer contracts") + require.Equal(t, numberOfContracts, len(results), "Incorrect number of Keeper Consumer Contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - return keeperConsumerContracts + return results } +// DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. func DeployKeeperConsumersPerformance( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, blockRange, // How many blocks to run the test for blockInterval, // Interval of blocks that upkeeps are expected to be performed @@ -455,7 +444,8 @@ func DeployKeeperConsumersPerformance( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - keeperConsumerInstance, err := contractDeployer.DeployKeeperConsumerPerformance( + keeperConsumerInstance, err := contracts.DeployKeeperConsumerPerformance( + client, big.NewInt(blockRange), big.NewInt(blockInterval), big.NewInt(checkGasToBurn), @@ -468,22 +458,18 @@ func DeployKeeperConsumersPerformance( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Performance Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumerPerformance deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + + require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of consumers contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeeps } +// DeployPerformDataChecker sequentially deploys keeper perform data checker contracts. func DeployPerformDataChecker( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, expectedData []byte, ) []contracts.KeeperPerformDataChecker { @@ -491,7 +477,7 @@ func DeployPerformDataChecker( upkeeps := make([]contracts.KeeperPerformDataChecker, 0) for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - performDataCheckerInstance, err := contractDeployer.DeployKeeperPerformDataChecker(expectedData) + performDataCheckerInstance, err := contracts.DeployKeeperPerformDataChecker(client, expectedData) require.NoError(t, err, "Deploying KeeperPerformDataChecker instance %d shouldn't fail", contractCount+1) upkeeps = append(upkeeps, performDataCheckerInstance) l.Debug(). @@ -499,22 +485,17 @@ func DeployPerformDataChecker( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed PerformDataChecker Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for PerformDataChecker deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper perform data checker contracts") + require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of PerformDataChecker contracts deployed") l.Info().Msg("Successfully deployed all PerformDataChecker Contracts") return upkeeps } +// DeployUpkeepCounters sequentially deploys a set amount of upkeep counter contracts. func DeployUpkeepCounters( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, testRange *big.Int, interval *big.Int, @@ -524,7 +505,7 @@ func DeployUpkeepCounters( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - upkeepCounter, err := contractDeployer.DeployUpkeepCounter(testRange, interval) + upkeepCounter, err := contracts.DeployUpkeepCounter(client, testRange, interval) require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) upkeepCounters = append(upkeepCounters, upkeepCounter) l.Debug(). @@ -532,22 +513,17 @@ func DeployUpkeepCounters( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeepCounters } +// DeployUpkeepPerformCounter sequentially deploys a set amount of upkeep perform counter restrictive contracts. func DeployUpkeepPerformCounterRestrictive( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, testRange *big.Int, averageEligibilityCadence *big.Int, @@ -557,7 +533,7 @@ func DeployUpkeepPerformCounterRestrictive( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - upkeepCounter, err := contractDeployer.DeployUpkeepPerformCounterRestrictive(testRange, averageEligibilityCadence) + upkeepCounter, err := contracts.DeployUpkeepPerformCounterRestrictive(client, testRange, averageEligibilityCadence) require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) upkeepCounters = append(upkeepCounters, upkeepCounter) l.Debug(). @@ -565,39 +541,89 @@ func DeployUpkeepPerformCounterRestrictive( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeepCounters } -// RegisterNewUpkeeps registers the given amount of new upkeeps, using the registry and registrar -// which are passed as parameters. -// It returns the newly deployed contracts (consumers), as well as their upkeep IDs. +// RegisterNewUpkeeps concurrently registers the given amount of new upkeeps, using the registry and registrar, +// which are passed as parameters. It returns the newly deployed contracts (consumers), as well as their upkeep IDs. func RegisterNewUpkeeps( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + chainClient *seth.Client, linkToken contracts.LinkToken, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, upkeepGasLimit uint32, numberOfNewUpkeeps int, ) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfNewUpkeeps, false, false) + newlyDeployedUpkeeps := DeployKeeperConsumers(t, chainClient, numberOfNewUpkeeps, false, false) var addressesOfNewUpkeeps []string for _, upkeep := range newlyDeployedUpkeeps { addressesOfNewUpkeeps = append(addressesOfNewUpkeeps, upkeep.Address()) } - newUpkeepIDs := RegisterUpkeepContracts(t, linkToken, big.NewInt(9e18), client, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) + concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + operationsPerAddress := numberOfNewUpkeeps / concurrency + + multicallAddress, err := contracts.DeployMultiCallContract(chainClient) + require.NoError(t, err, "Error deploying multicall contract") + + linkFundsForEachUpkeep := big.NewInt(9e18) + + err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + + newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) return newlyDeployedUpkeeps, newUpkeepIDs } + +var INSUFFICIENT_EPHEMERAL_KEYS = ` +Error: Insufficient Ephemeral Addresses for Simulated Network + +To operate on a simulated network, you must configure at least one ephemeral address. Currently, %d ephemeral address(es) are set. Please update your TOML configuration file as follows to meet this requirement: +[Seth] ephemeral_addresses_number = 1 + +This adjustment ensures that your setup is minimaly viable. Although it is highly recommended to use at least 20 ephemeral addresses. +` + +var INSUFFICIENT_STATIC_KEYS = ` +Error: Insufficient Private Keys for Live Network + +To run this test on a live network, you must either: +1. Set at least two private keys in the '[Network.WalletKeys]' section of your TOML configuration file. Example format: + [Network.WalletKeys] + NETWORK_NAME=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] +2. Set at least two private keys in the '[Network.EVMNetworks.NETWORK_NAME] section of your TOML configuration file. Example format: + evm_keys=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] + +Currently, only %d private key/s is/are set. + +Recommended Action: +Distribute your funds across multiple private keys and update your configuration accordingly. Even though 1 private key is sufficient for testing, it is highly recommended to use at least 10 private keys. +` + +// GetAndAssertCorrectConcurrency checks Seth configuration for the number of ephemeral keys or static keys (depending on Seth configuration) and makes sure that +// the number is at least minConcurrency. If the number is less than minConcurrency, it returns an error. The root key is always excluded from the count. +func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { + concurrency := client.Cfg.GetMaxConcurrency() + + var msg string + if client.Cfg.IsSimulatedNetwork() { + msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) + } else { + msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) + } + + if concurrency < minConcurrency { + return 0, fmt.Errorf(msg) + } + + return concurrency, nil +} diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index e5f9beff748..0f8dd9b29f2 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -4,14 +4,12 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" - "math/big" "strings" "time" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/lib/pq" - "github.com/rs/zerolog" "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" @@ -20,7 +18,6 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -32,82 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) -// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRv2Contracts -func DeployOCRv2Contracts( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - transmitters []string, - client blockchain.EVMClient, - ocrOptions contracts.OffchainOptions, -) ([]contracts.OffchainAggregatorV2, error) { - var ocrInstances []contracts.OffchainAggregatorV2 - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffchainAggregatorV2( - linkTokenContract.Address(), - ocrOptions, - ) - if err != nil { - return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCRv2 contract deployments: %w", err) - } - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCRv2 contract deployments: %w", err) - } - - // Gather address payees - var payees []string - for range transmitters { - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - } - return ocrInstances, client.WaitForEvents() -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.ConfigureOCRv2AggregatorContracts -func ConfigureOCRv2AggregatorContracts( - client blockchain.EVMClient, - contractConfig *contracts.OCRv2Config, - ocrv2Contracts []contracts.OffchainAggregatorV2, -) error { - for contractCount, ocrInstance := range ocrv2Contracts { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig(contractConfig) - if err != nil { - return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - } - return client.WaitForEvents() -} - // BuildMedianOCR2Config builds a default OCRv2 config for the given chainlink nodes for a standard median aggregation job func BuildMedianOCR2Config( workerNodes []*client.ChainlinkK8sClient, @@ -371,53 +292,6 @@ func CreateOCRv2Jobs( return nil } -// StartNewOCR2Round requests a new round from the ocr2 contracts and waits for confirmation -func StartNewOCR2Round( - roundNumber int64, - ocrInstances []contracts.OffchainAggregatorV2, - client blockchain.EVMClient, - timeout time.Duration, - logger zerolog.Logger, -) error { - time.Sleep(5 * time.Second) - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - ocrRound := contracts.NewOffchainAggregatorV2RoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), timeout, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err = ocrRound.Wait() // wait for OCR Round to complete - if err != nil { - return fmt.Errorf("failed to wait for OCR Round %d to complete instance %d", roundNumber, i) - } - if !ocrRound.Complete() { - return fmt.Errorf("failed to complete OCR Round %d for ocr instance %d", roundNumber, i) - } - } - return nil -} - -// WatchNewOCR2Round is the same as StartNewOCR2Round but does NOT explicitly request a new round -// as that can cause odd behavior in tandem with changing adapter values in OCR2 -func WatchNewOCR2Round( - roundNumber int64, - ocrInstances []contracts.OffchainAggregatorV2, - client blockchain.EVMClient, - timeout time.Duration, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - ocrRound := contracts.NewOffchainAggregatorV2RoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), timeout, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err := client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - // SetOCR2AdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node // used for OCR2 tests func SetOCR2AdapterResponse( @@ -460,34 +334,6 @@ func SetOCR2AllAdapterResponsesToTheSameValue( return eg.Wait() } -// SetOCR2AllAdapterResponsesToDifferentValues sets the mock responses in mockserver that are read by chainlink nodes -// to simulate different adapters. This sets all adapter responses for each node and contract to different responses -// used for OCR2 tests -func SetOCR2AllAdapterResponsesToDifferentValues( - responses []int, - ocrInstances []contracts.OffchainAggregatorV2, - chainlinkNodes []*client.ChainlinkK8sClient, - mockserver *ctfClient.MockserverClient, -) error { - if len(responses) != len(ocrInstances)*len(chainlinkNodes) { - return fmt.Errorf( - "amount of responses %d should be equal to the amount of OCR instances %d times the amount of Chainlink nodes %d", - len(responses), len(ocrInstances), len(chainlinkNodes), - ) - } - eg := &errgroup.Group{} - for _, o := range ocrInstances { - ocrInstance := o - for ni := 1; ni < len(chainlinkNodes); ni++ { - nodeIndex := ni - eg.Go(func() error { - return SetOCR2AdapterResponse(responses[nodeIndex-1], ocrInstance, chainlinkNodes[nodeIndex], mockserver) - }) - } - } - return eg.Wait() -} - // BuildOCR2NodeContractPairID builds a UUID based on a related pair of a Chainlink node and OCRv2 contract func BuildOCR2NodeContractPairID(node *client.ChainlinkK8sClient, ocrInstance contracts.OffchainAggregatorV2) (string, error) { if node == nil { diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go index 61989def0c8..cda6fa72ca2 100644 --- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go +++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -322,7 +322,7 @@ func SetupOCR2VRFUniverse( // fund OCR Nodes (so that they can transmit) nodes := contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes) - err = actions_seth.FundChainlinkNodesFromRootAddress(l, chainClient, nodes, ocr2vrf_constants.EthFundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, nodes, ocr2vrf_constants.EthFundingAmount) require.NoError(t, err, "Error funding Nodes") bootstrapNode := chainlinkNodes[0] diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 89a9d1574d2..6e54e81cd84 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -2,17 +2,13 @@ package actions import ( "fmt" - "math/big" "strings" "testing" - "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/rs/zerolog" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -22,163 +18,6 @@ import ( // This actions file often returns functions, rather than just values. These are used as common test helpers, and are // handy to have returning as functions so that Ginkgo can use them in an aesthetically pleasing way. -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRContracts -func DeployOCRContracts( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCR contract deployments: %w", err) - } - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contract deployments: %w", err) - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, node := range workerNodes { - addr, err := node.PrimaryEthAddress() - if err != nil { - return nil, fmt.Errorf("error getting node's primary ETH address: %w", err) - } - transmitters = append(transmitters, addr) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set payees and transmitters: %w", err) - } - - // Set Config - transmitterAddresses, err := ChainlinkNodeAddresses(workerNodes) - if err != nil { - return nil, fmt.Errorf("getting node common addresses should not fail: %w", err) - } - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set config: %w", err) - } - return ocrInstances, nil -} - -// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain -// aggregator contracts with forwarders as effectiveTransmitters -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRContractsForwarderFlow -func DeployOCRContractsForwarderFlow( - t *testing.T, - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkK8sClient, - forwarderAddresses []common.Address, - client blockchain.EVMClient, -) []contracts.OffchainAggregator { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - require.NoError(t, err, "Deploying OCR instance %d shouldn't fail", contractCount+1) - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for OCR Contract deployments") - } - } - err := client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contract deployments") - - // Gather transmitter and address payees - var transmitters, payees []string - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - require.NoError(t, err, "Error setting OCR payees") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for setting OCR payees") - } - } - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contracts to set payees and transmitters") - - // Set Config - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - forwarderAddresses, - ) - require.NoError(t, err, "Error setting OCR config for contract '%d'", ocrInstance.Address()) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for setting OCR config") - } - } - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contracts to set config") - return ocrInstances -} - // CreateOCRJobs bootstraps the first node and to the other nodes sends ocr jobs that // read from different adapters, to be used in combination with SetAdapterResponses func CreateOCRJobs( @@ -322,49 +161,6 @@ func CreateOCRJobsWithForwarder( } } -// StartNewRound requests a new round from the ocr contracts and waits for confirmation -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.StartNewRound -func StartNewRound( - roundNumber int64, - ocrInstances []contracts.OffchainAggregator, - client blockchain.EVMClient, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), client.GetNetworkConfig().Timeout.Duration, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err = client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - -// WatchNewRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new -// round from the contract, as this can cause some odd behavior in some cases -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.WatchNewRound -func WatchNewRound( - roundNumber int64, - ocrInstances []contracts.OffchainAggregator, - client blockchain.EVMClient, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), client.GetNetworkConfig().Timeout.Duration, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err := client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - // SetAdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node func SetAdapterResponse( response int, @@ -405,33 +201,6 @@ func SetAllAdapterResponsesToTheSameValue( return eg.Wait() } -// SetAllAdapterResponsesToDifferentValues sets the mock responses in mockserver that are read by chainlink nodes -// to simulate different adapters. This sets all adapter responses for each node and contract to different responses -func SetAllAdapterResponsesToDifferentValues( - responses []int, - ocrInstances []contracts.OffchainAggregator, - chainlinkNodes []*client.ChainlinkK8sClient, - mockserver *ctfClient.MockserverClient, -) error { - if len(responses) != len(ocrInstances)*len(chainlinkNodes) { - return fmt.Errorf( - "amount of responses %d should be equal to the amount of OCR instances %d times the amount of Chainlink nodes %d", - len(responses), len(ocrInstances), len(chainlinkNodes), - ) - } - eg := &errgroup.Group{} - for _, o := range ocrInstances { - ocrInstance := o - for ni := 1; ni < len(chainlinkNodes); ni++ { - nodeIndex := ni - eg.Go(func() error { - return SetAdapterResponse(responses[nodeIndex-1], ocrInstance, chainlinkNodes[nodeIndex], mockserver) - }) - } - } - return eg.Wait() -} - // BuildNodeContractPairID builds a UUID based on a related pair of a Chainlink node and OCR contract func BuildNodeContractPairID(node contracts.ChainlinkNodeWithKeysAndAddress, ocrInstance contracts.OffchainAggregator) (string, error) { if node == nil { diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index 1a7371517a4..0b415277f27 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -6,13 +6,10 @@ import ( "net/http" "strings" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/rs/zerolog" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -24,32 +21,6 @@ import ( Please, use them while refactoring other tests to local docker env */ -// FundChainlinkNodesLocal will fund all the provided Chainlink nodes with a set amount of native currency -func FundChainlinkNodesLocal( - nodes []*client.ChainlinkClient, - client blockchain.EVMClient, - amount *big.Float, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() - if err != nil { - return err - } - toAddr := common.HexToAddress(toAddress) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(toAddress, amount, gasEstimates) - if err != nil { - return err - } - } - return client.WaitForEvents() -} - func ChainlinkNodeAddressesLocal(nodes []*client.ChainlinkClient) ([]common.Address, error) { addresses := make([]common.Address, 0) for _, node := range nodes { @@ -62,85 +33,6 @@ func ChainlinkNodeAddressesLocal(nodes []*client.ChainlinkClient) ([]common.Addr return addresses, nil } -func DeployOCRContractsLocal( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkClient, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCR contract deployments: %w", err) - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contract deployments: %w", err) - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, node := range workerNodes { - addr, err := node.PrimaryEthAddress() - if err != nil { - return nil, fmt.Errorf("error getting node's primary ETH address: %w", err) - } - transmitters = append(transmitters, addr) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for _, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - - // Set Config - transmitterAddresses, err := ChainlinkNodeAddressesLocal(workerNodes) - if err != nil { - return nil, fmt.Errorf("getting node common addresses should not fail: %w", err) - } - - for _, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set config: %w", err) - } - return ocrInstances, nil -} - func CreateOCRJobsLocal( ocrInstances []contracts.OffchainAggregator, bootstrapNode *client.ChainlinkClient, @@ -256,92 +148,6 @@ func SetAllAdapterResponsesToTheSameValueLocal( return eg.Wait() } -func TrackForwarderLocal( - chainClient blockchain.EVMClient, - authorizedForwarder common.Address, - node *client.ChainlinkClient, - logger zerolog.Logger, -) error { - chainID := chainClient.GetChainID() - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - if err != nil { - return fmt.Errorf("failed to track forwarder, err: %w", err) - } - logger.Info().Str("NodeURL", node.Config.URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") - return nil -} - -func DeployOCRContractsForwarderFlowLocal( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkClient, - forwarderAddresses []common.Address, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("failed to deploy offchain aggregator, err: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - err = client.WaitForEvents() - if err != nil { - return nil, err - } - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for _, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("failed to set OCR payees, err: %w", err) - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - - // Set Config - for _, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig( - contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - forwarderAddresses, - ) - if err != nil { - return nil, fmt.Errorf("failed to set on-chain config, err: %w", err) - } - if err = client.WaitForEvents(); err != nil { - return nil, err - } - } - return ocrInstances, client.WaitForEvents() -} - func CreateOCRJobsWithForwarderLocal( ocrInstances []contracts.OffchainAggregator, bootstrapNode *client.ChainlinkClient, diff --git a/integration-tests/actions/operator_forwarder_helpers.go b/integration-tests/actions/operator_forwarder_helpers.go deleted file mode 100644 index 31eed7b7aae..00000000000 --- a/integration-tests/actions/operator_forwarder_helpers.go +++ /dev/null @@ -1,198 +0,0 @@ -package actions - -import ( - "math/big" - "testing" - - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" -) - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployForwarderContracts -func DeployForwarderContracts( - t *testing.T, - contractDeployer contracts.ContractDeployer, - linkToken contracts.LinkToken, - chainClient blockchain.EVMClient, - numberOfOperatorForwarderPairs int, -) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { - operatorFactoryInstance, err := contractDeployer.DeployOperatorFactory(linkToken.Address()) - require.NoError(t, err, "Deploying OperatorFactory Contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for deployment of flux aggregator contract") - - operatorCreated := make(chan *operator_factory.OperatorFactoryOperatorCreated) - authorizedForwarderCreated := make(chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated) - for i := 0; i < numberOfOperatorForwarderPairs; i++ { - SubscribeOperatorFactoryEvents(t, authorizedForwarderCreated, operatorCreated, chainClient, operatorFactoryInstance) - _, err = operatorFactoryInstance.DeployNewOperatorAndForwarder() - require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for events in nodes shouldn't fail") - eventDataAuthorizedForwarder, eventDataOperatorCreated := <-authorizedForwarderCreated, <-operatorCreated - operator, authorizedForwarder := eventDataOperatorCreated.Operator, eventDataAuthorizedForwarder.Forwarder - operators = append(operators, operator) - authorizedForwarders = append(authorizedForwarders, authorizedForwarder) - } - err = chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for events") - return operators, authorizedForwarders, operatorFactoryInstance -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.AcceptAuthorizedReceiversOperator -func AcceptAuthorizedReceiversOperator( - t *testing.T, - operator common.Address, - authorizedForwarder common.Address, - nodeAddresses []common.Address, - chainClient blockchain.EVMClient, - contractLoader contracts.ContractLoader, -) { - operatorInstance, err := contractLoader.LoadOperatorContract(operator) - require.NoError(t, err, "Loading operator contract shouldn't fail") - forwarderInstance, err := contractLoader.LoadAuthorizedForwarder(authorizedForwarder) - require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") - - err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) - require.NoError(t, err, "Accepting authorized receivers shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for events in nodes shouldn't fail") - - senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized senders shouldn't fail") - var nodesAddrs []string - for _, o := range nodeAddresses { - nodesAddrs = append(nodesAddrs, o.Hex()) - } - require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") - - owner, err := forwarderInstance.Owner(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") - require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") -} - -func ProcessNewEvent( - t *testing.T, - operatorCreated chan *operator_factory.OperatorFactoryOperatorCreated, - authorizedForwarderCreated chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated, - event *types.Log, - eventDetails *abi.Event, - operatorFactoryInstance contracts.OperatorFactory, - chainClient blockchain.EVMClient, -) { - l := logging.GetTestLogger(t) - errorChan := make(chan error) - eventConfirmed := make(chan bool) - err := chainClient.ProcessEvent(eventDetails.Name, event, eventConfirmed, errorChan) - if err != nil { - l.Error().Err(err).Str("Hash", event.TxHash.Hex()).Str("Event", eventDetails.Name).Msg("Error trying to process event") - return - } - l.Debug(). - Str("Event", eventDetails.Name). - Str("Address", event.Address.Hex()). - Str("Hash", event.TxHash.Hex()). - Msg("Attempting to Confirm Event") - for { - select { - case err := <-errorChan: - l.Error().Err(err).Msg("Error while confirming event") - return - case confirmed := <-eventConfirmed: - if confirmed { - if eventDetails.Name == "AuthorizedForwarderCreated" { // AuthorizedForwarderCreated event to authorizedForwarderCreated channel to handle in main loop - eventData, err := operatorFactoryInstance.ParseAuthorizedForwarderCreated(*event) - require.NoError(t, err, "Parsing OperatorFactoryAuthorizedForwarderCreated event log in "+ - "OperatorFactory instance shouldn't fail") - authorizedForwarderCreated <- eventData - } - if eventDetails.Name == "OperatorCreated" { // OperatorCreated event to operatorCreated channel to handle in main loop - eventData, err := operatorFactoryInstance.ParseOperatorCreated(*event) - require.NoError(t, err, "Parsing OperatorFactoryAuthorizedForwarderCreated event log in "+ - "OperatorFactory instance shouldn't fail") - operatorCreated <- eventData - } - } - return - } - } -} - -// SubscribeOperatorFactoryEvents subscribes to the event log for authorizedForwarderCreated and operatorCreated events -// from OperatorFactory contract -func SubscribeOperatorFactoryEvents( - t *testing.T, - authorizedForwarderCreated chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated, - operatorCreated chan *operator_factory.OperatorFactoryOperatorCreated, - chainClient blockchain.EVMClient, - operatorFactoryInstance contracts.OperatorFactory, -) { - l := logging.GetTestLogger(t) - contractABI, err := operator_factory.OperatorFactoryMetaData.GetAbi() - require.NoError(t, err, "Getting contract abi for OperatorFactory shouldn't fail") - latestBlockNum, err := chainClient.LatestBlockNumber(testcontext.Get(t)) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - query := geth.FilterQuery{ - FromBlock: big.NewInt(0).SetUint64(latestBlockNum), - Addresses: []common.Address{common.HexToAddress(operatorFactoryInstance.Address())}, - } - - eventLogs := make(chan types.Log) - sub, err := chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - go func() { - defer sub.Unsubscribe() - remainingExpectedEvents := 2 - for { - select { - case err := <-sub.Err(): - l.Error().Err(err).Msg("Error while watching for new contract events. Retrying Subscription") - sub.Unsubscribe() - - sub, err = chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - case vLog := <-eventLogs: - eventDetails, err := contractABI.EventByID(vLog.Topics[0]) - require.NoError(t, err, "Getting event details for OperatorFactory instance shouldn't fail") - go ProcessNewEvent( - t, operatorCreated, authorizedForwarderCreated, &vLog, - eventDetails, operatorFactoryInstance, chainClient, - ) - if eventDetails.Name == "AuthorizedForwarderCreated" || eventDetails.Name == "OperatorCreated" { - remainingExpectedEvents-- - if remainingExpectedEvents <= 0 { - return - } - } - } - } - }() -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.TrackForwarder -func TrackForwarder( - t *testing.T, - chainClient blockchain.EVMClient, - authorizedForwarder common.Address, - node *client.ChainlinkK8sClient, -) { - l := logging.GetTestLogger(t) - chainID := chainClient.GetChainID() - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - require.NoError(t, err, "Forwarder track should be created") - l.Info().Str("NodeURL", node.Config.URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") -} diff --git a/integration-tests/actions/seth/refund.go b/integration-tests/actions/refund.go similarity index 99% rename from integration-tests/actions/seth/refund.go rename to integration-tests/actions/refund.go index bd15fe7a0c9..38c4dfad3b9 100644 --- a/integration-tests/actions/seth/refund.go +++ b/integration-tests/actions/refund.go @@ -1,4 +1,4 @@ -package actions_seth +package actions import ( "context" @@ -234,7 +234,7 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg // insufficient funds, and retrying with a higher gas limit if the transaction fails due to gas too low. func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkNodeWithKeysAndAddress) error { if client == nil { - return fmt.Errorf("Seth client is nil, unable to return funds from chainlink nodes") + return fmt.Errorf("seth client is nil, unable to return funds from chainlink nodes") } log.Info().Msg("Attempting to return Chainlink node funds to default network wallets") if client.Cfg.IsSimulatedNetwork() { @@ -243,8 +243,7 @@ func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNode return nil } - failedReturns := []common.Address{} - + var failedReturns []common.Address for _, chainlinkNode := range chainlinkNodes { fundedKeys, err := chainlinkNode.ExportEVMKeysForChain(fmt.Sprint(client.ChainID)) if err != nil { diff --git a/integration-tests/actions/seth/actions.go b/integration-tests/actions/seth/actions.go deleted file mode 100644 index 719f71002b4..00000000000 --- a/integration-tests/actions/seth/actions.go +++ /dev/null @@ -1,1118 +0,0 @@ -package actions_seth - -import ( - "context" - "crypto/ecdsa" - "fmt" - "math" - "math/big" - "strings" - "testing" - "time" - - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" - "github.com/pkg/errors" - "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/test-go/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -var ContractDeploymentInterval = 200 - -// FundChainlinkNodesFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node -// from root private key. It returns an error if any of the transactions failed. -func FundChainlinkNodesFromRootAddress( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - amount *big.Float, -) error { - if len(client.PrivateKeys) == 0 { - return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) - } - - return FundChainlinkNodes(logger, client, nodes, client.PrivateKeys[0], amount) -} - -// FundChainlinkNodes sends native token amount (expressed in human-scale) to each Chainlink Node -// from private key's address. It returns an error if any of the transactions failed. -func FundChainlinkNodes( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, -) error { - keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { - return cl.PrimaryEthAddress() - } - return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) -} - -// FundChainlinkNodesAtKeyIndexFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node -// from root private key.It returns an error if any of the transactions failed. It sends the funds to -// node address at keyIndex (as each node can have multiple addresses). -func FundChainlinkNodesAtKeyIndexFromRootAddress( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - amount *big.Float, - keyIndex int, -) error { - if len(client.PrivateKeys) == 0 { - return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) - } - - return FundChainlinkNodesAtKeyIndex(logger, client, nodes, client.PrivateKeys[0], amount, keyIndex) -} - -// FundChainlinkNodesAtKeyIndex sends native token amount (expressed in human-scale) to each Chainlink Node -// from private key's address. It returns an error if any of the transactions failed. It sends the funds to -// node address at keyIndex (as each node can have multiple addresses). -func FundChainlinkNodesAtKeyIndex( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, - keyIndex int, -) error { - keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { - toAddress, err := cl.EthAddresses() - if err != nil { - return "", err - } - return toAddress[keyIndex], nil - } - return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) -} - -func fundChainlinkNodesAtAnyKey( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, - keyAddressFn func(contracts.ChainlinkNodeWithKeysAndAddress) (string, error), -) error { - for _, cl := range nodes { - toAddress, err := keyAddressFn(cl) - if err != nil { - return err - } - - fromAddress, err := privateKeyToAddress(privateKey) - if err != nil { - return err - } - - receipt, err := SendFunds(logger, client, FundsToSendPayload{ - ToAddress: common.HexToAddress(toAddress), - Amount: conversions.EtherToWei(amount), - PrivateKey: privateKey, - }) - if err != nil { - logger.Err(err). - Str("From", fromAddress.Hex()). - Str("To", toAddress). - Msg("Failed to fund Chainlink node") - - return err - } - - txHash := "(none)" - if receipt != nil { - txHash = receipt.TxHash.String() - } - - logger.Info(). - Str("From", fromAddress.Hex()). - Str("To", toAddress). - Str("TxHash", txHash). - Str("Amount", amount.String()). - Msg("Funded Chainlink node") - } - - return nil -} - -type FundsToSendPayload struct { - ToAddress common.Address - Amount *big.Int - PrivateKey *ecdsa.PrivateKey - GasLimit *int64 - GasPrice *big.Int - GasFeeCap *big.Int - GasTipCap *big.Int - TxTimeout *time.Duration -} - -// TODO: move to CTF? -// SendFunds sends native token amount (expressed in human-scale) from address controlled by private key -// to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap. -// Values that are not set will be estimated or taken from config. -func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) { - fromAddress, err := privateKeyToAddress(payload.PrivateKey) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.Background(), client.Cfg.Network.TxnTimeout.Duration()) - nonce, err := client.Client.PendingNonceAt(ctx, fromAddress) - defer cancel() - if err != nil { - return nil, err - } - - var gasLimit int64 - gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) - if err != nil { - gasLimit = client.Cfg.Network.TransferGasFee - } else { - gasLimit = int64(gasLimitRaw) - } - - gasPrice := big.NewInt(0) - gasFeeCap := big.NewInt(0) - gasTipCap := big.NewInt(0) - - if payload.GasLimit != nil { - gasLimit = *payload.GasLimit - } - - if client.Cfg.Network.EIP1559DynamicFees { - // if any of the dynamic fees are not set, we need to either estimate them or read them from config - if payload.GasFeeCap == nil || payload.GasTipCap == nil { - // estimation or config reading happens here - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) - gasFeeCap = txOptions.GasFeeCap - gasTipCap = txOptions.GasTipCap - } - - // override with payload values if they are set - if payload.GasFeeCap != nil { - gasFeeCap = payload.GasFeeCap - } - - if payload.GasTipCap != nil { - gasTipCap = payload.GasTipCap - } - } else { - if payload.GasPrice == nil { - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) - gasPrice = txOptions.GasPrice - } else { - gasPrice = payload.GasPrice - } - } - - var rawTx types.TxData - - if client.Cfg.Network.EIP1559DynamicFees { - rawTx = &types.DynamicFeeTx{ - Nonce: nonce, - To: &payload.ToAddress, - Value: payload.Amount, - Gas: uint64(gasLimit), - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - } - } else { - rawTx = &types.LegacyTx{ - Nonce: nonce, - To: &payload.ToAddress, - Value: payload.Amount, - Gas: uint64(gasLimit), - GasPrice: gasPrice, - } - } - - signedTx, err := types.SignNewTx(payload.PrivateKey, types.LatestSignerForChainID(big.NewInt(client.ChainID)), rawTx) - - if err != nil { - return nil, errors.Wrap(err, "failed to sign tx") - } - - txTimeout := client.Cfg.Network.TxnTimeout.Duration() - if payload.TxTimeout != nil { - txTimeout = *payload.TxTimeout - } - - logger.Debug(). - Str("From", fromAddress.Hex()). - Str("To", payload.ToAddress.Hex()). - Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). - Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). - Str("Gas Price", gasPrice.String()). - Str("Gas Fee Cap", gasFeeCap.String()). - Str("Gas Tip Cap", gasTipCap.String()). - Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). - Msg("About to send funds") - - ctx, cancel = context.WithTimeout(ctx, txTimeout) - defer cancel() - err = client.Client.SendTransaction(ctx, signedTx) - if err != nil { - return nil, errors.Wrap(err, "failed to send transaction") - } - - logger.Debug(). - Str("From", fromAddress.Hex()). - Str("To", payload.ToAddress.Hex()). - Str("TxHash", signedTx.Hash().String()). - Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). - Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). - Str("Gas Price", gasPrice.String()). - Str("Gas Fee Cap", gasFeeCap.String()). - Str("Gas Tip Cap", gasTipCap.String()). - Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). - Msg("Sent funds") - - receipt, receiptErr := client.WaitMined(ctx, logger, client.Client, signedTx) - if receiptErr != nil { - return nil, errors.Wrap(receiptErr, "failed to wait for transaction to be mined") - } - - if receipt.Status == 1 { - return receipt, nil - } - - tx, _, err := client.Client.TransactionByHash(ctx, signedTx.Hash()) - if err != nil { - return nil, errors.Wrap(err, "failed to get transaction by hash ") - } - - _, err = client.Decode(tx, receiptErr) - if err != nil { - return nil, err - } - - return receipt, nil -} - -// DeployForwarderContracts first deploys Operator Factory and then uses it to deploy given number of -// operator and forwarder pairs. It waits for each transaction to be mined and then extracts operator and -// forwarder addresses from emitted events. -func DeployForwarderContracts( - t *testing.T, - seth *seth.Client, - linkTokenAddress common.Address, - numberOfOperatorForwarderPairs int, -) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { - instance, err := contracts.DeployEthereumOperatorFactory(seth, linkTokenAddress) - require.NoError(t, err, "failed to create new instance of operator factory") - operatorFactoryInstance = &instance - - for i := 0; i < numberOfOperatorForwarderPairs; i++ { - decodedTx, err := seth.Decode(operatorFactoryInstance.DeployNewOperatorAndForwarder()) - require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") - - for i, event := range decodedTx.Events { - require.True(t, len(event.Topics) > 0, fmt.Sprintf("Event %d should have topics", i)) - switch event.Topics[0] { - case operator_factory.OperatorFactoryOperatorCreated{}.Topic().String(): - if address, ok := event.EventData["operator"]; ok { - operators = append(operators, address.(common.Address)) - } else { - require.Fail(t, "Operator address not found in event", event) - } - case operator_factory.OperatorFactoryAuthorizedForwarderCreated{}.Topic().String(): - if address, ok := event.EventData["forwarder"]; ok { - authorizedForwarders = append(authorizedForwarders, address.(common.Address)) - } else { - require.Fail(t, "Forwarder address not found in event", event) - } - } - } - } - return operators, authorizedForwarders, operatorFactoryInstance -} - -// WatchNewOCRRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new -// round from the contract, as this can cause some odd behavior in some cases. It announces success if latest round -// is >= roundNumber. -func WatchNewOCRRound( - l zerolog.Logger, - seth *seth.Client, - roundNumber int64, - ocrInstances []contracts.OffChainAggregatorWithRounds, - timeout time.Duration, -) error { - confirmed := make(map[string]bool) - timeoutC := time.After(timeout) - ticker := time.NewTicker(time.Millisecond * 200) - defer ticker.Stop() - - l.Info().Msgf("Waiting for round %d to be confirmed by all nodes", roundNumber) - - for { - select { - case <-timeoutC: - return fmt.Errorf("timeout waiting for round %d to be confirmed. %d/%d nodes confirmed it", roundNumber, len(confirmed), len(ocrInstances)) - case <-ticker.C: - for i := 0; i < len(ocrInstances); i++ { - if confirmed[ocrInstances[i].Address()] { - continue - } - ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) - roundData, err := ocrInstances[i].GetLatestRound(ctx) - if err != nil { - cancel() - return fmt.Errorf("getting latest round from OCR instance %d have failed: %w", i+1, err) - } - cancel() - if roundData.RoundId.Cmp(big.NewInt(roundNumber)) >= 0 { - l.Debug().Msgf("OCR instance %d/%d confirmed round %d", i+1, len(ocrInstances), roundNumber) - confirmed[ocrInstances[i].Address()] = true - } - } - if len(confirmed) == len(ocrInstances) { - return nil - } - } - } -} - -// AcceptAuthorizedReceiversOperator sets authorized receivers for each operator contract to -// authorizedForwarder and authorized EA to nodeAddresses. Once done, it confirms that authorizations -// were set correctly. -func AcceptAuthorizedReceiversOperator( - t *testing.T, - logger zerolog.Logger, - seth *seth.Client, - operator common.Address, - authorizedForwarder common.Address, - nodeAddresses []common.Address, -) { - operatorInstance, err := contracts.LoadEthereumOperator(logger, seth, operator) - require.NoError(t, err, "Loading operator contract shouldn't fail") - forwarderInstance, err := contracts.LoadEthereumAuthorizedForwarder(seth, authorizedForwarder) - require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") - - err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) - require.NoError(t, err, "Accepting authorized forwarder shouldn't fail") - - senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized senders shouldn't fail") - var nodesAddrs []string - for _, o := range nodeAddresses { - nodesAddrs = append(nodesAddrs, o.Hex()) - } - require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") - - owner, err := forwarderInstance.Owner(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") - require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") -} - -// TrackForwarder creates forwarder track for a given Chainlink node -func TrackForwarder( - t *testing.T, - seth *seth.Client, - authorizedForwarder common.Address, - node contracts.ChainlinkNodeWithForwarder, -) { - l := logging.GetTestLogger(t) - chainID := big.NewInt(seth.ChainID) - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - require.NoError(t, err, "Forwarder track should be created") - l.Info().Str("NodeURL", node.GetConfig().URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") -} - -// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults -func DeployOCRv2Contracts( - l zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenAddress common.Address, - transmitters []string, - ocrOptions contracts.OffchainOptions, -) ([]contracts.OffchainAggregatorV2, error) { - var ocrInstances []contracts.OffchainAggregatorV2 - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregatorV2( - l, - seth, - linkTokenAddress, - ocrOptions, - ) - if err != nil { - return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Gather address payees - var payees []string - for range transmitters { - payees = append(payees, seth.Addresses[0].Hex()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - return ocrInstances, nil -} - -// ConfigureOCRv2AggregatorContracts sets configuration for a number of OCRv2 contracts -func ConfigureOCRv2AggregatorContracts( - contractConfig *contracts.OCRv2Config, - ocrv2Contracts []contracts.OffchainAggregatorV2, -) error { - for contractCount, ocrInstance := range ocrv2Contracts { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig(contractConfig) - if err != nil { - return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - return nil -} - -// TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the -// specified path. Can also accept a testreporter (if one was used) to log further results -func TeardownSuite( - t *testing.T, - chainClient *seth.Client, - env *environment.Environment, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level - grafnaUrlProvider testreporters.GrafanaURLProvider, -) error { - l := logging.GetTestLogger(t) - if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { - return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err) - } - // Delete all jobs to stop depleting the funds - err := DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - if chainlinkNodes != nil { - if err := ReturnFundsFromNodes(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { - // This printed line is required for tests that use real funds to propagate the failure - // out to the system running the test. Do not remove - fmt.Println(environment.FAILED_FUND_RETURN) - l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - } else { - l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") - } - - return env.Shutdown() -} - -// TeardownRemoteSuite sends a report and returns funds from chainlink nodes to network's default wallet -func TeardownRemoteSuite( - t *testing.T, - client *seth.Client, - namespace string, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - grafnaUrlProvider testreporters.GrafanaURLProvider, -) error { - l := logging.GetTestLogger(t) - if err := testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { - l.Warn().Err(err).Msg("Error writing test report") - } - // Delete all jobs to stop depleting the funds - err := DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - if err = ReturnFundsFromNodes(l, client, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { - l.Error().Err(err).Str("Namespace", namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - - return err -} - -// DeleteAllJobs deletes all jobs from all chainlink nodes -// added here temporarily to avoid circular import -func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { - for _, node := range chainlinkNodes { - if node == nil { - return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", chainlinkNodes) - } - jobs, _, err := node.ReadJobs() - if err != nil { - return fmt.Errorf("error reading jobs from chainlink node, err: %w", err) - } - for _, maps := range jobs.Data { - if _, ok := maps["id"]; !ok { - return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data) - } - id := maps["id"].(string) - _, err := node.DeleteJob(id) - if err != nil { - return fmt.Errorf("error deleting job from chainlink node, err: %w", err) - } - } - } - return nil -} - -// StartNewRound requests a new round from the ocr contracts and returns once transaction was mined -func StartNewRound( - ocrInstances []contracts.OffChainAggregatorWithRounds, -) error { - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - } - return nil -} - -// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain -// aggregator contracts with forwarders as effectiveTransmitters -func DeployOCRContractsForwarderFlow( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, - forwarderAddresses []common.Address, -) ([]contracts.OffchainAggregator, error) { - transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { - transmitters = make([]string, 0) - payees = make([]string, 0) - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, seth.Addresses[0].Hex()) - } - - return - } - - transmitterAddressesFn := func() ([]common.Address, error) { - return forwarderAddresses, nil - } - - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) -} - -// DeployOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts -func DeployOCRv1Contracts( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, -) ([]contracts.OffchainAggregator, error) { - transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { - transmitters = make([]string, 0) - payees = make([]string, 0) - for _, node := range workerNodes { - var addr string - addr, err = node.PrimaryEthAddress() - if err != nil { - err = fmt.Errorf("error getting node's primary ETH address: %w", err) - return - } - transmitters = append(transmitters, addr) - payees = append(payees, seth.Addresses[0].Hex()) - } - - return - } - - transmitterAddressesFn := func() ([]common.Address, error) { - transmitterAddresses := make([]common.Address, 0) - for _, node := range workerNodes { - primaryAddress, err := node.PrimaryEthAddress() - if err != nil { - return nil, err - } - transmitterAddresses = append(transmitterAddresses, common.HexToAddress(primaryAddress)) - } - - return transmitterAddresses, nil - } - - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) -} - -func deployAnyOCRv1Contracts( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, - getTransmitterAndPayeesFn func() ([]string, []string, error), - getTransmitterAddressesFn func() ([]common.Address, error), -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Gather transmitter and address payees - var transmitters, payees []string - var err error - transmitters, payees, err = getTransmitterAndPayeesFn() - if err != nil { - return nil, fmt.Errorf("error getting transmitter and payees: %w", err) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Set Config - transmitterAddresses, err := getTransmitterAddressesFn() - if err != nil { - return nil, fmt.Errorf("getting transmitter addresses should not fail: %w", err) - } - - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - workerNodes, - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - return ocrInstances, nil -} - -func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { - publicKey := privateKey.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - return common.Address{}, errors.New("error casting public key to ECDSA") - } - return crypto.PubkeyToAddress(*publicKeyECDSA), nil -} - -func WatchNewFluxRound( - l zerolog.Logger, - seth *seth.Client, - roundNumber int64, - fluxInstance contracts.FluxAggregator, - timeout time.Duration, -) error { - timeoutC := time.After(timeout) - ticker := time.NewTicker(time.Millisecond * 200) - defer ticker.Stop() - - l.Info().Msgf("Waiting for flux round %d to be confirmed by flux aggregator", roundNumber) - - for { - select { - case <-timeoutC: - return fmt.Errorf("timeout waiting for round %d to be confirmed", roundNumber) - case <-ticker.C: - ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) - roundId, err := fluxInstance.LatestRoundID(ctx) - if err != nil { - cancel() - return fmt.Errorf("getting latest round from flux instance has failed: %w", err) - } - cancel() - if roundId.Cmp(big.NewInt(roundNumber)) >= 0 { - l.Debug().Msgf("Flux instance confirmed round %d", roundNumber) - return nil - } - } - } -} - -// EstimateCostForChainlinkOperations estimates the cost of running a number of operations on the Chainlink node based on estimated gas costs. It supports -// both legacy and EIP-1559 transactions. -func EstimateCostForChainlinkOperations(l zerolog.Logger, client *seth.Client, network blockchain.EVMNetwork, amountOfOperations int) (*big.Float, error) { - bigAmountOfOperations := big.NewInt(int64(amountOfOperations)) - estimations := client.CalculateGasEstimations(client.NewDefaultGasEstimationRequest()) - - gasLimit := network.GasEstimationBuffer + network.ChainlinkTransactionLimit - - var gasPriceInWei *big.Int - if client.Cfg.Network.EIP1559DynamicFees { - gasPriceInWei = estimations.GasFeeCap - } else { - gasPriceInWei = estimations.GasPrice - } - - gasCostPerOperationWei := big.NewInt(1).Mul(big.NewInt(1).SetUint64(gasLimit), gasPriceInWei) - gasCostPerOperationETH := conversions.WeiToEther(gasCostPerOperationWei) - // total Wei needed for all TXs = total value for TX * number of TXs - totalWeiForAllOperations := big.NewInt(1).Mul(gasCostPerOperationWei, bigAmountOfOperations) - totalEthForAllOperations := conversions.WeiToEther(totalWeiForAllOperations) - - l.Debug(). - Int("Number of Operations", amountOfOperations). - Uint64("Gas Limit per Operation", gasLimit). - Str("Value per Operation (ETH)", gasCostPerOperationETH.String()). - Str("Total (ETH)", totalEthForAllOperations.String()). - Msg("Calculated ETH for Chainlink Operations") - - return totalEthForAllOperations, nil -} - -// GetLatestFinalizedBlockHeader returns latest finalised block header for given network (taking into account finality tag/depth) -func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, network blockchain.EVMNetwork) (*types.Header, error) { - if network.FinalityTag { - return client.Client.HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64())) - } - if network.FinalityDepth == 0 { - return nil, fmt.Errorf("finality depth is 0 and finality tag is not enabled") - } - header, err := client.Client.HeaderByNumber(ctx, nil) - if err != nil { - return nil, err - } - latestBlockNumber := header.Number.Uint64() - finalizedBlockNumber := latestBlockNumber - network.FinalityDepth - return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) -} - -// SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses -// Multicall contract to batch all transfers in a single transaction. It also checks if the funds were transferred correctly. -// It's primary use case is to fund addresses that will be used for Upkeep registration (as that requires LINK balance) during -// Automation/Keeper test setup. -func SendLinkFundsToDeploymentAddresses( - chainClient *seth.Client, - concurrency, - totalUpkeeps, - operationsPerAddress int, - multicallAddress common.Address, - linkAmountPerUpkeep *big.Int, - linkToken contracts.LinkToken, -) error { - var generateCallData = func(receiver common.Address, amount *big.Int) ([]byte, error) { - abi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return nil, err - } - data, err := abi.Pack("transfer", receiver, amount) - if err != nil { - return nil, err - } - return data, nil - } - - toTransferToMultiCallContract := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(totalUpkeeps+concurrency))) - toTransferPerClient := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(operationsPerAddress+1))) - err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) - if err != nil { - return errors.Wrapf(err, "Error transferring LINK to multicall contract") - } - - balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) - if err != nil { - return errors.Wrapf(err, "Error getting LINK balance of multicall contract") - } - - if balance.Cmp(toTransferToMultiCallContract) < 0 { - return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), balance.String()) - } - - // Transfer LINK to ephemeral keys - multiCallData := make([][]byte, 0) - for i := 1; i <= concurrency; i++ { - data, err := generateCallData(chainClient.Addresses[i], toTransferPerClient) - if err != nil { - return errors.Wrapf(err, "Error generating call data for LINK transfer") - } - multiCallData = append(multiCallData, data) - } - - var call []contracts.Call - for _, d := range multiCallData { - data := contracts.Call{Target: common.HexToAddress(linkToken.Address()), AllowFailure: false, CallData: d} - call = append(call, data) - } - - multiCallABI, err := abi.JSON(strings.NewReader(contracts.MultiCallABI)) - if err != nil { - return errors.Wrapf(err, "Error getting Multicall contract ABI") - } - boundContract := bind.NewBoundContract(multicallAddress, multiCallABI, chainClient.Client, chainClient.Client, chainClient.Client) - // call aggregate3 to group all msg call data and send them in a single transaction - _, err = chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) - if err != nil { - return errors.Wrapf(err, "Error calling Multicall contract") - } - - for i := 1; i <= concurrency; i++ { - balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) - if err != nil { - return errors.Wrapf(err, "Error getting LINK balance of ephemeral key %d", i) - } - if balance.Cmp(toTransferPerClient) < 0 { - return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), balance.String()) - } - } - - return nil -} - -var noOpSethConfigFn = func(_ *seth.Config) error { return nil } - -type SethConfigFunction = func(*seth.Config) error - -// OneEphemeralKeysLiveTestnetCheckFn checks whether there's at least one ephemeral key on a simulated network or at least one static key on a live network, -// and that there are no ephemeral keys on a live network. Root key is excluded from the check. -var OneEphemeralKeysLiveTestnetCheckFn = func(sethCfg *seth.Config) error { - concurrency := sethCfg.GetMaxConcurrency() - - if sethCfg.IsSimulatedNetwork() { - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, 0) - } - - return nil - } - - if sethCfg.EphemeralAddrs != nil && int(*sethCfg.EphemeralAddrs) > 0 { - ephMsg := ` - Error: Ephemeral Addresses Detected on Live Network - - Ephemeral addresses are currently set for use on a live network, which is not permitted. The number of ephemeral addresses set is %d. Please make the following update to your TOML configuration file to correct this: - '[Seth] ephemeral_addresses_number = 0' - - Additionally, ensure the following requirements are met to run this test on a live network: - 1. Use more than one private key in your network configuration. - ` - - return errors.New(ephMsg) - } - - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_STATIC_KEYS, len(sethCfg.Network.PrivateKeys)) - } - - return nil -} - -// OneEphemeralKeysLiveTestnetAutoFixFn checks whether there's at least one ephemeral key on a simulated network or at least one static key on a live network, -// and that there are no epehemeral keys on a live network (if ephemeral keys count is different from zero, it will disable them). Root key is excluded from the check. -var OneEphemeralKeysLiveTestnetAutoFixFn = func(sethCfg *seth.Config) error { - concurrency := sethCfg.GetMaxConcurrency() - - if sethCfg.IsSimulatedNetwork() { - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, 0) - } - - return nil - } - - if sethCfg.EphemeralAddrs != nil && int(*sethCfg.EphemeralAddrs) > 0 { - var zero int64 = 0 - sethCfg.EphemeralAddrs = &zero - } - - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_STATIC_KEYS, len(sethCfg.Network.PrivateKeys)) - } - - return nil -} - -// GetChainClient returns a seth client for the given network after validating the config -func GetChainClient(config ctf_config.SethConfig, network blockchain.EVMNetwork) (*seth.Client, error) { - return GetChainClientWithConfigFunction(config, network, noOpSethConfigFn) -} - -// GetChainClientWithConfigFunction returns a seth client for the given network after validating the config and applying the config function -func GetChainClientWithConfigFunction(config ctf_config.SethConfig, network blockchain.EVMNetwork, configFn SethConfigFunction) (*seth.Client, error) { - readSethCfg := config.GetSethConfig() - if readSethCfg == nil { - return nil, fmt.Errorf("Seth config not found") - } - - sethCfg, err := seth_utils.MergeSethAndEvmNetworkConfigs(network, *readSethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error merging seth and evm network configs") - } - - err = configFn(&sethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error applying seth config function") - } - - err = seth_utils.ValidateSethNetworkConfig(sethCfg.Network) - if err != nil { - return nil, errors.Wrapf(err, "Error validating seth network config") - } - - chainClient, err := seth.NewClientWithConfig(&sethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error creating seth client") - } - - return chainClient, nil -} - -// GenerateUpkeepReport generates a report of performed, successful, reverted and stale upkeeps for a given registry contract based on transaction logs. In case of test failure it can help us -// to triage the issue by providing more context. -func GenerateUpkeepReport(t *testing.T, chainClient *seth.Client, startBlock, endBlock *big.Int, instance contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) (performedUpkeeps, successfulUpkeeps, revertedUpkeeps, staleUpkeeps int, err error) { - registryLogs := []gethtypes.Log{} - l := logging.GetTestLogger(t) - - var ( - blockBatchSize int64 = 100 - logs []gethtypes.Log - timeout = 5 * time.Second - addr = common.HexToAddress(instance.Address()) - queryStartBlock = startBlock - ) - - // Gather logs from the registry in 100 block chunks to avoid read limits - for queryStartBlock.Cmp(endBlock) < 0 { - filterQuery := geth.FilterQuery{ - Addresses: []common.Address{addr}, - FromBlock: queryStartBlock, - ToBlock: big.NewInt(0).Add(queryStartBlock, big.NewInt(blockBatchSize)), - } - - // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats. - err = fmt.Errorf("initial error") // to ensure our for loop runs at least once - for err != nil { - ctx, cancel := context.WithTimeout(testcontext.Get(t), timeout) - logs, err = chainClient.Client.FilterLogs(ctx, filterQuery) - cancel() - if err != nil { - l.Error(). - Err(err). - Interface("Filter Query", filterQuery). - Str("Timeout", timeout.String()). - Msg("Error getting logs from chain, trying again") - timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) - continue - } - l.Info(). - Uint64("From Block", queryStartBlock.Uint64()). - Uint64("To Block", filterQuery.ToBlock.Uint64()). - Int("Log Count", len(logs)). - Str("Registry Address", addr.Hex()). - Msg("Collected logs") - queryStartBlock.Add(queryStartBlock, big.NewInt(blockBatchSize)) - registryLogs = append(registryLogs, logs...) - } - } - - var contractABI *abi.ABI - contractABI, err = contracts.GetRegistryContractABI(registryVersion) - if err != nil { - return - } - - for _, allLogs := range registryLogs { - log := allLogs - var eventDetails *abi.Event - eventDetails, err = contractABI.EventByID(log.Topics[0]) - if err != nil { - l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error getting event details for log, report data inaccurate") - break - } - if eventDetails.Name == "UpkeepPerformed" { - performedUpkeeps++ - var parsedLog *contracts.UpkeepPerformedLog - parsedLog, err = instance.ParseUpkeepPerformedLog(&log) - if err != nil { - l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error parsing upkeep performed log, report data inaccurate") - break - } - if !parsedLog.Success { - revertedUpkeeps++ - } else { - successfulUpkeeps++ - } - } else if eventDetails.Name == "StaleUpkeepReport" { - staleUpkeeps++ - } - } - - return -} - -func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClient *seth.Client, startBlock uint64, registry contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) func() { - return func() { - if t.Failed() { - endBlock, err := chainClient.Client.BlockNumber(context.Background()) - require.NoError(t, err, "Failed to get end block") - - total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) - require.NoError(t, err, "Failed to get staleness data") - if stale > 0 || reverted > 0 { - logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") - } else { - logger.Info().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") - } - } - } -} diff --git a/integration-tests/actions/seth/automation_ocr_helpers.go b/integration-tests/actions/seth/automation_ocr_helpers.go deleted file mode 100644 index 160937869ab..00000000000 --- a/integration-tests/actions/seth/automation_ocr_helpers.go +++ /dev/null @@ -1,176 +0,0 @@ -package actions_seth - -import ( - "math" - "math/big" - "testing" - - "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -// DeployAutoOCRRegistryAndRegistrar registry and registrar -func DeployAutoOCRRegistryAndRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - linkToken contracts.LinkToken, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar) { - registry := deployRegistry(t, client, registryVersion, registrySettings, linkToken) - registrar := deployRegistrar(t, client, registryVersion, registry, linkToken) - - return registry, registrar -} - -// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - upkeeps := DeployKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury) - require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts( - t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, - ) - require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") - return upkeeps, upkeepIds -} - -// DeployPerformanceConsumers deploys and registers keeper performance consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkeep will be registered with root key address as the admin. -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployPerformanceConsumers( - t *testing.T, - chainClient *seth.Client, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, - upkeepGasLimit uint32, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) ([]contracts.KeeperConsumerPerformance, []*big.Int) { - upkeeps := DeployKeeperConsumersPerformance( - t, chainClient, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, - ) - - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - return upkeeps, upkeepIds -} - -// DeployPerformDataCheckerConsumers deploys and registers keeper performance data checkers consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deployes multicall contract and sends link funds to each deployment address. -func DeployPerformDataCheckerConsumers( - t *testing.T, - chainClient *seth.Client, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, - upkeepGasLimit uint32, - expectedData []byte, -) ([]contracts.KeeperPerformDataChecker, []*big.Int) { - upkeeps := DeployPerformDataChecker(t, chainClient, numberOfUpkeeps, expectedData) - - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - return upkeeps, upkeepIds -} - -// DeployMultiCallAndFundDeploymentAddresses deploys multicall contract and sends link funds to each deployment address -func DeployMultiCallAndFundDeploymentAddresses( - chainClient *seth.Client, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, -) error { - concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) - if err != nil { - return err - } - - operationsPerAddress := numberOfUpkeeps / concurrency - - multicallAddress, err := contracts.DeployMultiCallContract(chainClient) - if err != nil { - return errors.Wrap(err, "Error deploying multicall contract") - } - - return SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) -} - -func deployRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registry contracts.KeeperRegistry, - linkToken contracts.LinkToken, -) contracts.KeeperRegistrar { - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) - require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - return registrar -} - -func deployRegistry( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - linkToken contracts.LinkToken, -) contracts.KeeperRegistry { - ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - // Deploy the transcoder here, and then set it to the registry - transcoder, err := contracts.DeployUpkeepTranscoder(client) - require.NoError(t, err, "Deploying upkeep transcoder shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - client, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: transcoder.Address(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry contract shouldn't fail") - return registry -} diff --git a/integration-tests/actions/seth/keeper_helpers.go b/integration-tests/actions/seth/keeper_helpers.go deleted file mode 100644 index 09b23e5f8f6..00000000000 --- a/integration-tests/actions/seth/keeper_helpers.go +++ /dev/null @@ -1,580 +0,0 @@ -package actions_seth - -import ( - "context" - "fmt" - "math" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - "github.com/stretchr/testify/require" - - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -var ZeroAddress = common.Address{} - -// DeployKeeperContracts deploys keeper registry and a number of basic upkeep contracts with an update interval of 5. -// It returns the freshly deployed registry, registrar, consumers and the IDs of the upkeeps. -func DeployKeeperContracts( - t *testing.T, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - numberOfUpkeeps int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - client *seth.Client, - linkFundsForEachUpkeep *big.Int, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumer, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - // Deploy the transcoder here, and then set it to the registry - transcoder, err := contracts.DeployUpkeepTranscoder(client) - require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - client, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: transcoder.Address(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - - registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) - upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -// DeployPerformanceKeeperContracts deploys a set amount of keeper performance contracts registered to a single registry -func DeployPerformanceKeeperContracts( - t *testing.T, - chainClient *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - numberOfContracts int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - registrySettings *contracts.KeeperRegistrySettings, - linkFundsForEachUpkeep *big.Int, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumerPerformance, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - chainClient, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: ZeroAddress.Hex(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: *registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) - - err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - upkeeps := DeployKeeperConsumersPerformance( - t, chainClient, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, - ) - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -// DeployPerformDataCheckerContracts deploys a set amount of keeper perform data checker contracts registered to a single registry -func DeployPerformDataCheckerContracts( - t *testing.T, - chainClient *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - numberOfContracts int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - registrySettings *contracts.KeeperRegistrySettings, - linkFundsForEachUpkeep *big.Int, - expectedData []byte, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperPerformDataChecker, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - chainClient, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: ZeroAddress.Hex(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: *registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - - registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) - upkeeps := DeployPerformDataChecker(t, chainClient, numberOfContracts, expectedData) - - err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -func DeployKeeperRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - linkToken contracts.LinkToken, - registrarSettings contracts.KeeperRegistrarSettings, - registry contracts.KeeperRegistry, -) contracts.KeeperRegistrar { - registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) - require.NoError(t, err, "Failed waiting for registrar to deploy") - if registryVersion != ethereum.RegistryVersion_2_0 { - err = registry.SetRegistrar(registrar.Address()) - require.NoError(t, err, "Registering the registrar address on the registry shouldn't fail") - } - - return registrar -} - -func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { - checkData := make([][]byte, 0) - for i := 0; i < numberOfContracts; i++ { - checkData = append(checkData, []byte("0")) - } - return RegisterUpkeepContractsWithCheckData( - t, client, linkToken, linkFunds, upkeepGasLimit, registry, registrar, - numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury) -} - -type upkeepRegistrationResult struct { - upkeepID UpkeepId -} - -func (r upkeepRegistrationResult) GetResult() *big.Int { - return r.upkeepID -} - -type upkeepConfig struct { - address string - data []byte -} - -type UpkeepId = *big.Int - -func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { - l := logging.GetTestLogger(t) - - concurrency, err := GetAndAssertCorrectConcurrency(client, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - executor := ctf_concurrency.NewConcurrentExecutor[UpkeepId, upkeepRegistrationResult, upkeepConfig](l) - - configs := make([]upkeepConfig, 0) - for i := 0; i < len(upkeepAddresses); i++ { - configs = append(configs, upkeepConfig{address: upkeepAddresses[i], data: checkData[i]}) - } - - var registerUpkeepFn = func(resultCh chan upkeepRegistrationResult, errorCh chan error, executorNum int, config upkeepConfig) { - uuid := uuid.New().String() - keyNum := executorNum + 1 // key 0 is the root key - - req, err := registrar.EncodeRegisterRequest( - fmt.Sprintf("upkeep_%s", uuid), - []byte("test@mail.com"), - config.address, - upkeepGasLimit, - client.MustGetRootKeyAddress().Hex(), // upkeep Admin - config.data, - linkFunds, - 0, - client.Addresses[keyNum].Hex(), - isLogTrigger, - isMercury, - ) - - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to encode register request for upkeep at %s", uuid, config.address) - return - } - - balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s]Failed to get LINK balance of %s", uuid, client.Addresses[keyNum].Hex()) - return - } - - // not stricly necessary, but helps us to avoid an errorless revert if there is not enough LINK - if balance.Cmp(linkFunds) < 0 { - errorCh <- fmt.Errorf("[uuid: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", uuid, client.Addresses[keyNum].Hex(), balance.String(), linkFunds.String()) - return - } - - tx, err := linkToken.TransferAndCallFromKey(registrar.Address(), linkFunds, req, keyNum) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to register upkeep at %s", uuid, config.address) - return - } - - receipt, err := client.Client.TransactionReceipt(context.Background(), tx.Hash()) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to get receipt for upkeep at %s and tx hash %s", uuid, config.address, tx.Hash()) - return - } - - var upkeepId *big.Int - for _, rawLog := range receipt.Logs { - parsedUpkeepId, err := registry.ParseUpkeepIdFromRegisteredLog(rawLog) - if err == nil { - upkeepId = parsedUpkeepId - break - } - } - - if upkeepId == nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed find upkeep ID for upkeep at %s in logs of tx with hash %s", uuid, config.address, tx.Hash()) - return - } - - l.Debug(). - Str("TxHash", tx.Hash().String()). - Str("Upkeep ID", upkeepId.String()). - Msg("Found upkeepId in tx hash") - - resultCh <- upkeepRegistrationResult{upkeepID: upkeepId} - } - - upkeepIds, err := executor.Execute(concurrency, configs, registerUpkeepFn) - require.NoError(t, err, "Failed to register upkeeps using executor") - - require.Equal(t, numberOfContracts, len(upkeepIds), "Incorrect number of Keeper Consumer Contracts registered") - l.Info().Msg("Successfully registered all Keeper Consumer Contracts") - - return upkeepIds -} - -type keeperConsumerResult struct { - contract contracts.KeeperConsumer -} - -func (k keeperConsumerResult) GetResult() contracts.KeeperConsumer { - return k.contract -} - -// DeployKeeperConsumers concurrently deploys keeper consumer contracts. It requires at least 1 ephemeral key to be present in Seth config. -func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { - l := logging.GetTestLogger(t) - - concurrency, err := GetAndAssertCorrectConcurrency(client, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - executor := ctf_concurrency.NewConcurrentExecutor[contracts.KeeperConsumer, keeperConsumerResult, ctf_concurrency.NoTaskType](l) - - var deployContractFn = func(channel chan keeperConsumerResult, _ chan error, executorNum int) { - keyNum := executorNum + 1 // key 0 is the root key - var keeperConsumerInstance contracts.KeeperConsumer - var err error - - if isMercury && isLogTrigger { - // v2.1 only: Log triggered based contract with Mercury enabled - keeperConsumerInstance, err = contracts.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumerFromKey(client, keyNum) - } else if isMercury { - // v2.1 only: Conditional based contract with Mercury enabled - keeperConsumerInstance, err = contracts.DeployAutomationStreamsLookupUpkeepConsumerFromKey(client, keyNum, big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range - } else if isLogTrigger { - // v2.1 only: Log triggered based contract without Mercury - keeperConsumerInstance, err = contracts.DeployAutomationLogTriggerConsumerFromKey(client, keyNum, big.NewInt(1000)) // 1000 block test range - } else { - // v2.0 and v2.1: Conditional based contract without Mercury - keeperConsumerInstance, err = contracts.DeployUpkeepCounterFromKey(client, keyNum, big.NewInt(999999), big.NewInt(5)) - } - - require.NoError(t, err, "Deploying Consumer shouldn't fail") - - channel <- keeperConsumerResult{contract: keeperConsumerInstance} - } - - results, err := executor.ExecuteSimple(concurrency, numberOfContracts, deployContractFn) - require.NoError(t, err, "Failed to deploy keeper consumers") - - // require.Equal(t, 0, len(deplymentErrors), "Error deploying consumer contracts") - require.Equal(t, numberOfContracts, len(results), "Incorrect number of Keeper Consumer Contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return results -} - -// DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. -func DeployKeeperConsumersPerformance( - t *testing.T, - client *seth.Client, - numberOfContracts int, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) []contracts.KeeperConsumerPerformance { - l := logging.GetTestLogger(t) - upkeeps := make([]contracts.KeeperConsumerPerformance, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - keeperConsumerInstance, err := contracts.DeployKeeperConsumerPerformance( - client, - big.NewInt(blockRange), - big.NewInt(blockInterval), - big.NewInt(checkGasToBurn), - big.NewInt(performGasToBurn), - ) - require.NoError(t, err, "Deploying KeeperConsumerPerformance instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, keeperConsumerInstance) - l.Debug(). - Str("Contract Address", keeperConsumerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Performance Contract") - } - - require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of consumers contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeeps -} - -// DeployPerformDataChecker sequentially deploys keeper perform data checker contracts. -func DeployPerformDataChecker( - t *testing.T, - client *seth.Client, - numberOfContracts int, - expectedData []byte, -) []contracts.KeeperPerformDataChecker { - l := logging.GetTestLogger(t) - upkeeps := make([]contracts.KeeperPerformDataChecker, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - performDataCheckerInstance, err := contracts.DeployKeeperPerformDataChecker(client, expectedData) - require.NoError(t, err, "Deploying KeeperPerformDataChecker instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, performDataCheckerInstance) - l.Debug(). - Str("Contract Address", performDataCheckerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed PerformDataChecker Contract") - } - require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of PerformDataChecker contracts deployed") - l.Info().Msg("Successfully deployed all PerformDataChecker Contracts") - - return upkeeps -} - -// DeployUpkeepCounters sequentially deploys a set amount of upkeep counter contracts. -func DeployUpkeepCounters( - t *testing.T, - client *seth.Client, - numberOfContracts int, - testRange *big.Int, - interval *big.Int, -) []contracts.UpkeepCounter { - l := logging.GetTestLogger(t) - upkeepCounters := make([]contracts.UpkeepCounter, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - upkeepCounter, err := contracts.DeployUpkeepCounter(client, testRange, interval) - require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) - upkeepCounters = append(upkeepCounters, upkeepCounter) - l.Debug(). - Str("Contract Address", upkeepCounter.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - } - require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeepCounters -} - -// DeployUpkeepPerformCounter sequentially deploys a set amount of upkeep perform counter restrictive contracts. -func DeployUpkeepPerformCounterRestrictive( - t *testing.T, - client *seth.Client, - numberOfContracts int, - testRange *big.Int, - averageEligibilityCadence *big.Int, -) []contracts.UpkeepPerformCounterRestrictive { - l := logging.GetTestLogger(t) - upkeepCounters := make([]contracts.UpkeepPerformCounterRestrictive, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - upkeepCounter, err := contracts.DeployUpkeepPerformCounterRestrictive(client, testRange, averageEligibilityCadence) - require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) - upkeepCounters = append(upkeepCounters, upkeepCounter) - l.Debug(). - Str("Contract Address", upkeepCounter.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - } - require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeepCounters -} - -// RegisterNewUpkeeps concurrently registers the given amount of new upkeeps, using the registry and registrar, -// which are passed as parameters. It returns the newly deployed contracts (consumers), as well as their upkeep IDs. -func RegisterNewUpkeeps( - t *testing.T, - chainClient *seth.Client, - linkToken contracts.LinkToken, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - upkeepGasLimit uint32, - numberOfNewUpkeeps int, -) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, chainClient, numberOfNewUpkeeps, false, false) - - var addressesOfNewUpkeeps []string - for _, upkeep := range newlyDeployedUpkeeps { - addressesOfNewUpkeeps = append(addressesOfNewUpkeeps, upkeep.Address()) - } - - concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - operationsPerAddress := numberOfNewUpkeeps / concurrency - - multicallAddress, err := contracts.DeployMultiCallContract(chainClient) - require.NoError(t, err, "Error deploying multicall contract") - - linkFundsForEachUpkeep := big.NewInt(9e18) - - err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) - - return newlyDeployedUpkeeps, newUpkeepIDs -} - -var INSUFFICIENT_EPHEMERAL_KEYS = ` -Error: Insufficient Ephemeral Addresses for Simulated Network - -To operate on a simulated network, you must configure at least one ephemeral address. Currently, %d ephemeral address(es) are set. Please update your TOML configuration file as follows to meet this requirement: -[Seth] ephemeral_addresses_number = 1 - -This adjustment ensures that your setup is minimaly viable. Although it is highly recommended to use at least 20 ephemeral addresses. -` - -var INSUFFICIENT_STATIC_KEYS = ` -Error: Insufficient Private Keys for Live Network - -To run this test on a live network, you must either: -1. Set at least two private keys in the '[Network.WalletKeys]' section of your TOML configuration file. Example format: - [Network.WalletKeys] - NETWORK_NAME=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] -2. Set at least two private keys in the '[Network.EVMNetworks.NETWORK_NAME] section of your TOML configuration file. Example format: - evm_keys=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] - -Currently, only %d private key/s is/are set. - -Recommended Action: -Distribute your funds across multiple private keys and update your configuration accordingly. Even though 1 private key is sufficient for testing, it is highly recommended to use at least 10 private keys. -` - -// GetAndAssertCorrectConcurrency checks Seth configuration for the number of ephemeral keys or static keys (depending on Seth configuration) and makes sure that -// the number is at least minConcurrency. If the number is less than minConcurrency, it returns an error. The root key is always excluded from the count. -func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { - concurrency := client.Cfg.GetMaxConcurrency() - - var msg string - if client.Cfg.IsSimulatedNetwork() { - msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) - } else { - msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) - } - - if concurrency < minConcurrency { - return 0, fmt.Errorf(msg) - } - - return concurrency, nil -} diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index d57bdc33b90..db8b44efe95 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -2,12 +2,19 @@ package common import ( "context" + "encoding/json" "fmt" "math/big" + "os" "sync" "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/go-resty/resty/v2" + "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/rs/zerolog" @@ -16,7 +23,7 @@ import ( ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -65,7 +72,7 @@ func CreateAndFundSendingKeys( return nil, fmt.Errorf("error creating transaction key - response code, err %d", response.StatusCode) } newNativeTokenKeyAddresses = append(newNativeTokenKeyAddresses, newTxKey.Data.Attributes.Address) - _, err = actions_seth.SendFunds(l, client, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, client, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(newTxKey.Data.Attributes.Address), Amount: conversions.EtherToWei(big.NewFloat(chainlinkNodeFunding)), PrivateKey: client.PrivateKeys[0], @@ -78,7 +85,7 @@ func CreateAndFundSendingKeys( } func SetupBHSNode( - env *test_env.CLClusterTestEnv, + sethClient *seth.Client, config *vrf_common_config.General, numberOfTxKeysToCreate int, chainID *big.Int, @@ -88,11 +95,6 @@ func SetupBHSNode( l zerolog.Logger, bhsNode *VRFNode, ) error { - sethClient, err := env.GetSethClient(chainID.Int64()) - if err != nil { - return err - } - bhsTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys( l, sethClient, @@ -157,7 +159,7 @@ func CreateBHSJob( } func SetupBHFNode( - env *test_env.CLClusterTestEnv, + sethClient *seth.Client, config *vrf_common_config.General, numberOfTxKeysToCreate int, chainID *big.Int, @@ -168,10 +170,6 @@ func SetupBHFNode( l zerolog.Logger, bhfNode *VRFNode, ) error { - sethClient, err := env.GetSethClient(chainID.Int64()) - if err != nil { - return err - } bhfTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys( l, sethClient, @@ -336,7 +334,7 @@ func FundNodesIfNeeded(ctx context.Context, existingEnvConfig *vrf_common_config Str("Funding Amount in wei", fundingToSendWei.String()). Str("Funding Amount in ETH", conversions.WeiToEther(fundingToSendWei).String()). Msg("Funding Node's Sending Key") - _, err := actions_seth.SendFunds(l, client, actions_seth.FundsToSendPayload{ + _, err := actions.SendFunds(l, client, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(sendingKey), Amount: fundingToSendWei, PrivateKey: client.PrivateKeys[0], @@ -353,19 +351,129 @@ func FundNodesIfNeeded(ctx context.Context, existingEnvConfig *vrf_common_config return nil } -func BuildNewCLEnvForVRF(t *testing.T, envConfig VRFEnvConfig, newEnvConfig NewEnvConfig, network ctf_test_env.EthereumNetwork) (*test_env.CLClusterTestEnv, error) { +func BuildNewCLEnvForVRF(l zerolog.Logger, t *testing.T, envConfig VRFEnvConfig, newEnvConfig NewEnvConfig, network ctf_test_env.EthereumNetwork) (*test_env.CLClusterTestEnv, *seth.Client, error) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). - WithFunding(big.NewFloat(*envConfig.TestConfig.Common.ChainlinkNodeFunding)). WithChainlinkNodeLogScanner(newEnvConfig.ChainlinkNodeLogScannerSettings). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + } + + evmNetwork, err := env.GetFirstEvmNetwork() + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "error getting first evm network", err) + } + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "error getting seth client", err) + } + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*envConfig.TestConfig.Common.ChainlinkNodeFunding)) + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "failed to fund the nodes", err) + } + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + + return env, sethClient, nil +} + +func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { + provider, err := env.GetRpcProvider(chainID) + if err != nil { + return "", err + } + return provider.PublicHttpUrls()[0], nil +} + +// RPCRawClient +// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" +type RPCRawClient struct { + resty *resty.Client +} + +func NewRPCRawClient(url string) *RPCRawClient { + isDebug := os.Getenv("DEBUG_RESTY") == "true" + restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) + return &RPCRawClient{ + resty: restyClient, } - return env, nil +} + +func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { + var responseObject JsonRPCResponse + postBody, _ := json.Marshal(map[string]any{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_setHead", + "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, + }) + resp, err := g.resty.R(). + SetHeader("Content-Type", "application/json"). + SetBody(postBody). + SetResult(&responseObject). + Post("") + + if err != nil { + return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + } + statusCode := resp.StatusCode() + if statusCode != 200 && statusCode != 201 { + return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + } + if responseObject.Error != "" { + return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + } + return responseObject, nil +} + +type JsonRPCResponse struct { + Version string `json:"jsonrpc"` + Id int `json:"id"` + Result string `json:"result,omitempty"` + Error string `json:"error,omitempty"` +} + +// todo - move to CTF +func RewindSimulatedChainToBlockNumber( + ctx context.Context, + client *seth.Client, + rpcURL string, + rewindChainToBlockNumber uint64, + l zerolog.Logger, +) (uint64, error) { + latestBlockNumberBeforeReorg, err := client.Client.BlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Str("RPC URL", rpcURL). + Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). + Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). + Msg("Performing Reorg on chain by rewinding chain to specific block number") + + _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + + if err != nil { + return 0, fmt.Errorf("error making reorg: %w", err) + } + + latestBlockNumberAfterReorg, err := client.Client.BlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Uint64("Block Number", latestBlockNumberAfterReorg). + Msg("Latest Block Number after Reorg") + return latestBlockNumberAfterReorg, nil } diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 92da7b9f86b..4ea49a9b728 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -18,7 +18,6 @@ import ( vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -27,18 +26,12 @@ import ( ) func DeployVRFV2Contracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkTokenContract contracts.LinkToken, linkEthFeedContract contracts.VRFMockETHLINKFeed, useVRFOwner bool, useTestCoordinator bool, ) (*vrfcommon.VRFContracts, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } - bhs, err := contracts.DeployBlockhashStore(sethClient) if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployBlockHashStore, err) @@ -95,10 +88,10 @@ func DeployVRFV2Contracts( }, nil } -func DeployVRFV2Consumers(client *seth.Client, coordinatorAddress string, consumerContractsAmount int) ([]contracts.VRFv2LoadTestConsumer, error) { +func DeployVRFV2Consumers(sethClient *seth.Client, coordinatorAddress string, consumerContractsAmount int) ([]contracts.VRFv2LoadTestConsumer, error) { var consumers []contracts.VRFv2LoadTestConsumer for i := 1; i <= consumerContractsAmount; i++ { - loadTestConsumer, err := contracts.DeployVRFv2LoadTestConsumer(client, coordinatorAddress) + loadTestConsumer, err := contracts.DeployVRFv2LoadTestConsumer(sethClient, coordinatorAddress) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err) } @@ -107,10 +100,10 @@ func DeployVRFV2Consumers(client *seth.Client, coordinatorAddress string, consum return consumers, nil } -func DeployVRFV2WrapperConsumers(client *seth.Client, linkTokenAddress string, vrfV2Wrapper contracts.VRFV2Wrapper, consumerContractsAmount int) ([]contracts.VRFv2WrapperLoadTestConsumer, error) { +func DeployVRFV2WrapperConsumers(sethClient *seth.Client, linkTokenAddress string, vrfV2Wrapper contracts.VRFV2Wrapper, consumerContractsAmount int) ([]contracts.VRFv2WrapperLoadTestConsumer, error) { var consumers []contracts.VRFv2WrapperLoadTestConsumer for i := 1; i <= consumerContractsAmount; i++ { - loadTestConsumer, err := contracts.DeployVRFV2WrapperLoadTestConsumer(client, linkTokenAddress, vrfV2Wrapper.Address()) + loadTestConsumer, err := contracts.DeployVRFV2WrapperLoadTestConsumer(sethClient, linkTokenAddress, vrfV2Wrapper.Address()) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err) } @@ -120,17 +113,17 @@ func DeployVRFV2WrapperConsumers(client *seth.Client, linkTokenAddress string, v } func DeployVRFV2DirectFundingContracts( - client *seth.Client, + sethClient *seth.Client, linkTokenAddress string, linkEthFeedAddress string, coordinator contracts.VRFCoordinatorV2, consumerContractsAmount int, ) (*VRFV2WrapperContracts, error) { - vrfv2Wrapper, err := contracts.DeployVRFV2Wrapper(client, linkTokenAddress, linkEthFeedAddress, coordinator.Address()) + vrfv2Wrapper, err := contracts.DeployVRFV2Wrapper(sethClient, linkTokenAddress, linkEthFeedAddress, coordinator.Address()) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrDeployVRFV2Wrapper, err) } - consumers, err := DeployVRFV2WrapperConsumers(client, linkTokenAddress, vrfv2Wrapper, consumerContractsAmount) + consumers, err := DeployVRFV2WrapperConsumers(sethClient, linkTokenAddress, vrfv2Wrapper, consumerContractsAmount) if err != nil { return nil, err } @@ -157,8 +150,7 @@ func VRFV2RegisterProvingKey( } func SetupVRFV2Contracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, useVRFOwner bool, @@ -168,8 +160,7 @@ func SetupVRFV2Contracts( ) (*vrfcommon.VRFContracts, error) { l.Info().Msg("Deploying VRFV2 contracts") vrfContracts, err := DeployVRFV2Contracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, useVRFOwner, @@ -634,8 +625,7 @@ func SetupVRFOwnerContractIfNeeded(useVRFOwner bool, vrfContracts *vrfcommon.VRF } func SetupNewConsumersAndSubs( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2, testConfig tc.TestConfig, linkToken contracts.LinkToken, @@ -643,10 +633,6 @@ func SetupNewConsumersAndSubs( numberOfSubToCreate int, l zerolog.Logger, ) ([]contracts.VRFv2LoadTestConsumer, []uint64, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } consumers, err := DeployVRFV2Consumers(sethClient, coordinator.Address(), numberOfConsumerContractsToDeployAndAddToSub) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index 546508842db..c13aed807a9 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -6,6 +6,10 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "golang.org/x/sync/errgroup" @@ -75,6 +79,7 @@ func CreateVRFV2Job( // SetupVRFV2Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2Environment( ctx context.Context, + sethClient *seth.Client, env *test_env.CLClusterTestEnv, chainID int64, nodesToCreate []vrfcommon.VRFNodeType, @@ -90,8 +95,7 @@ func SetupVRFV2Environment( l.Info().Msg("Starting VRFV2 environment setup") configGeneral := vrfv2TestConfig.GetVRFv2Config().General vrfContracts, err := SetupVRFV2Contracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, useVRFOwner, @@ -122,11 +126,6 @@ func SetupVRFV2Environment( return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrCreatingProvingKeyHash, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, nil, err - } - vrfTXKeyAddressStrings, vrfTXKeyAddresses, err := vrfcommon.CreateFundAndGetSendingKeys( l, sethClient, @@ -160,7 +159,7 @@ func SetupVRFV2Environment( if bhsNode, exists := nodeTypeToNodeMap[vrfcommon.BHS]; exists { g.Go(func() error { err := vrfcommon.SetupBHSNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -236,8 +235,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, vrfv2Conf func SetupVRFV2WrapperEnvironment( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, vrfv2TestConfig tc.VRFv2TestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, @@ -245,11 +243,6 @@ func SetupVRFV2WrapperEnvironment( keyHash [32]byte, wrapperConsumerContractsAmount int, ) (*VRFV2WrapperContracts, *uint64, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } - // Deploy VRF v2 direct funding contracts wrapperContracts, err := DeployVRFV2DirectFundingContracts( sethClient, @@ -306,26 +299,28 @@ func SetupVRFV2Universe( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { var ( env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client err error ) if *envConfig.TestConfig.VRFv2.General.UseExistingEnv { - vrfContracts, vrfKey, env, err = SetupVRFV2ForExistingEnv(t, envConfig, l) + vrfContracts, vrfKey, env, sethClient, err = SetupVRFV2ForExistingEnv(t, envConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for Existing env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for Existing env", err) } } else { - vrfContracts, vrfKey, env, nodeTypeToNodeMap, err = SetupVRFV2ForNewEnv(ctx, t, envConfig, newEnvConfig, l) + vrfContracts, vrfKey, env, nodeTypeToNodeMap, sethClient, err = SetupVRFV2ForNewEnv(ctx, t, envConfig, newEnvConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for New env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for New env", err) } } - return env, vrfContracts, vrfKey, nodeTypeToNodeMap, nil + + return env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, nil } func SetupVRFV2ForNewEnv( @@ -334,29 +329,26 @@ func SetupVRFV2ForNewEnv( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { network, err := actions.EthereumNetworkConfigFromConfig(l, &envConfig.TestConfig) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2", err) } - env, err := vrfcommon.BuildNewCLEnvForVRF(t, envConfig, newEnvConfig, network) + env, sethClient, err := vrfcommon.BuildNewCLEnvForVRF(l, t, envConfig, newEnvConfig, network) if err != nil { - return nil, nil, nil, nil, err - } - sethClient, err := env.GetSethClientForSelectedNetwork() - if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } mockETHLinkFeed, err := contracts.DeployVRFMockETHLINKFeed(sethClient, big.NewInt(*envConfig.TestConfig.VRFv2.General.LinkNativeFeedResponse)) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) } linkToken, err := contracts.DeployLinkTokenContract(l, sethClient) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) } vrfContracts, vrfKey, nodeTypeToNode, err := SetupVRFV2Environment( ctx, + sethClient, env, envConfig.ChainID, newEnvConfig.NodesToCreate, @@ -371,50 +363,50 @@ func SetupVRFV2ForNewEnv( l, ) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2 env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2 env", err) } - return vrfContracts, vrfKey, env, nodeTypeToNode, nil + + return vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, nil } -func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, error) { +func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, *seth.Client, error) { commonExistingEnvConfig := envConfig.TestConfig.VRFv2.ExistingEnvConfig.ExistingEnvConfig env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) } - client, err := env.GetSethClientForSelectedNetwork() + evmNetwork, err := env.GetFirstEvmNetwork() if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } - coordinator, err := contracts.LoadVRFCoordinatorV2(client, *commonExistingEnvConfig.ConsumerAddress) + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2", err) + return nil, nil, nil, nil, err } - linkAddr := common.HexToAddress(*commonExistingEnvConfig.LinkAddress) - linkToken, err := contracts.LoadLinkTokenContract(l, client, linkAddr) + coordinator, err := contracts.LoadVRFCoordinatorV2(sethClient, *commonExistingEnvConfig.ConsumerAddress) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2", err) } - sethClient, err := env.GetSethClient(envConfig.ChainID) + linkAddr := common.HexToAddress(*commonExistingEnvConfig.LinkAddress) + linkToken, err := contracts.LoadLinkTokenContract(l, sethClient, linkAddr) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) } err = vrfcommon.FundNodesIfNeeded(testcontext.Get(t), commonExistingEnvConfig, sethClient, l) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStoreAddress, err := coordinator.GetBlockHashStoreAddress(testcontext.Get(t)) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStore, err := contracts.LoadBlockHashStore(sethClient, blockHashStoreAddress.String()) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) } vrfContracts := &vrfcommon.VRFContracts{ CoordinatorV2: coordinator, @@ -427,12 +419,11 @@ func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l EncodedProvingKey: [2]*big.Int{}, KeyHash: common.HexToHash(*commonExistingEnvConfig.KeyHash), } - return vrfContracts, vrfKey, env, nil + return vrfContracts, vrfKey, env, sethClient, nil } func SetupSubsAndConsumersForExistingEnv( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2, linkToken contracts.LinkToken, numberOfConsumerContractsToDeployAndAddToSub int, @@ -449,8 +440,7 @@ func SetupSubsAndConsumersForExistingEnv( commonExistingEnvConfig := testConfig.VRFv2.ExistingEnvConfig.ExistingEnvConfig if *commonExistingEnvConfig.CreateFundSubsAndAddConsumers { consumers, subIDs, err = SetupNewConsumersAndSubs( - env, - chainID, + sethClient, coordinator, testConfig, linkToken, @@ -462,12 +452,8 @@ func SetupSubsAndConsumersForExistingEnv( return nil, nil, fmt.Errorf("err: %w", err) } } else { - client, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } addr := common.HexToAddress(*commonExistingEnvConfig.ConsumerAddress) - consumer, err := contracts.LoadVRFv2LoadTestConsumer(client, addr) + consumer, err := contracts.LoadVRFv2LoadTestConsumer(sethClient, addr) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) } @@ -476,8 +462,7 @@ func SetupSubsAndConsumersForExistingEnv( } } else { consumers, subIDs, err = SetupNewConsumersAndSubs( - env, - chainID, + sethClient, coordinator, testConfig, linkToken, diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index ed6139c4f17..8d06678690f 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -18,7 +18,6 @@ import ( vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -121,8 +120,7 @@ func FundVRFCoordinatorV2_5Subscription( func CreateFundSubsAndAddConsumers( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, subscriptionFundingAmountNative *big.Float, subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, @@ -132,8 +130,7 @@ func CreateFundSubsAndAddConsumers( ) ([]*big.Int, error) { subIDs, err := CreateSubsAndFund( ctx, - env, - chainID, + sethClient, subscriptionFundingAmountNative, subscriptionFundingAmountLink, linkToken, @@ -160,15 +157,14 @@ func CreateFundSubsAndAddConsumers( func CreateSubsAndFund( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, subscriptionFundingAmountNative *big.Float, subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, subAmountToCreate int, ) ([]*big.Int, error) { - subs, err := CreateSubs(ctx, env, chainID, coordinator, subAmountToCreate) + subs, err := CreateSubs(ctx, sethClient, coordinator, subAmountToCreate) if err != nil { return nil, err } @@ -187,15 +183,14 @@ func CreateSubsAndFund( func CreateSubs( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, subAmountToCreate int, ) ([]*big.Int, error) { var subIDArr []*big.Int for i := 0; i < subAmountToCreate; i++ { - subID, err := CreateSubAndFindSubID(ctx, env, chainID, coordinator) + subID, err := CreateSubAndFindSubID(ctx, sethClient, coordinator) if err != nil { return nil, err } @@ -219,15 +214,11 @@ func AddConsumersToSubs( return nil } -func CreateSubAndFindSubID(ctx context.Context, env *test_env.CLClusterTestEnv, chainID int64, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) { +func CreateSubAndFindSubID(ctx context.Context, sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) { tx, err := coordinator.CreateSubscription() if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrCreateVRFSubscription, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } receipt, err := sethClient.Client.TransactionReceipt(ctx, tx.Hash()) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) @@ -508,18 +499,13 @@ func DeployVRFV2PlusWrapperConsumers(client *seth.Client, vrfV2PlusWrapper contr } func SetupVRFV2PlusContracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, configGeneral *vrfv2plus_config.General, l zerolog.Logger, ) (*vrfcommon.VRFContracts, error) { l.Info().Msg("Deploying VRFV2 Plus contracts") - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } vrfContracts, err := DeployVRFV2_5Contracts(sethClient) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployVRFV2_5Contracts, err) @@ -554,8 +540,7 @@ func SetupVRFV2PlusContracts( func SetupNewConsumersAndSubs( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, testConfig tc.TestConfig, linkToken contracts.LinkToken, @@ -563,10 +548,6 @@ func SetupNewConsumersAndSubs( numberOfSubToCreate int, l zerolog.Logger, ) ([]contracts.VRFv2PlusLoadTestConsumer, []*big.Int, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } consumers, err := DeployVRFV2PlusConsumers(sethClient, coordinator, consumerContractsAmount) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) @@ -577,8 +558,7 @@ func SetupNewConsumersAndSubs( Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err := CreateFundSubsAndAddConsumers( ctx, - env, - chainID, + sethClient, big.NewFloat(*testConfig.VRFv2Plus.General.SubscriptionFundingAmountNative), big.NewFloat(*testConfig.VRFv2Plus.General.SubscriptionFundingAmountLink), linkToken, diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 16fe1b9427f..63890c3b9de 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -6,6 +6,10 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/shopspring/decimal" "golang.org/x/sync/errgroup" @@ -15,13 +19,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -75,6 +78,7 @@ func CreateVRFV2PlusJob( // SetupVRFV2_5Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2_5Environment( ctx context.Context, + sethClient *seth.Client, env *test_env.CLClusterTestEnv, chainID int64, nodesToCreate []vrfcommon.VRFNodeType, @@ -86,9 +90,9 @@ func SetupVRFV2_5Environment( ) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { l.Info().Msg("Starting VRFV2 Plus environment setup") configGeneral := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General + vrfContracts, err := SetupVRFV2PlusContracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, configGeneral, @@ -116,11 +120,6 @@ func SetupVRFV2_5Environment( return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrCreatingProvingKeyHash, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, nil, err - } - vrfTXKeyAddressStrings, _, err := vrfcommon.CreateFundAndGetSendingKeys( l, sethClient, @@ -149,7 +148,7 @@ func SetupVRFV2_5Environment( if bhsNode, exists := nodeTypeToNodeMap[vrfcommon.BHS]; exists { g.Go(func() error { err := vrfcommon.SetupBHSNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -169,7 +168,7 @@ func SetupVRFV2_5Environment( if bhfNode, exists := nodeTypeToNodeMap[vrfcommon.BHF]; exists { g.Go(func() error { err := vrfcommon.SetupBHFNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -247,8 +246,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, config *v func SetupVRFV2PlusWrapperEnvironment( ctx context.Context, l zerolog.Logger, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, vrfv2PlusTestConfig types.VRFv2PlusTestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, @@ -257,18 +255,12 @@ func SetupVRFV2PlusWrapperEnvironment( wrapperConsumerContractsAmount int, ) (*VRFV2PlusWrapperContracts, *big.Int, error) { // external EOA has to create a subscription for the wrapper first - wrapperSubId, err := CreateSubAndFindSubID(ctx, env, chainID, coordinator) + wrapperSubId, err := CreateSubAndFindSubID(ctx, sethClient, coordinator) if err != nil { return nil, nil, err } vrfv2PlusConfig := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General - - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } - wrapperContracts, err := DeployVRFV2PlusDirectFundingContracts( sethClient, linkToken.Address(), @@ -332,7 +324,7 @@ func SetupVRFV2PlusWrapperEnvironment( } //fund consumer with Eth (native token) - _, err = actions_seth.SendFunds(l, sethClient, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, sethClient, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()), Amount: conversions.EtherToWei(big.NewFloat(*vrfv2PlusConfig.WrapperConsumerFundingAmountNativeToken)), PrivateKey: sethClient.PrivateKeys[0], @@ -359,26 +351,28 @@ func SetupVRFV2PlusUniverse( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { var ( env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts vrfKey *vrfcommon.VRFKeyData nodeTypeToNode map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client err error ) if *envConfig.TestConfig.VRFv2Plus.General.UseExistingEnv { - vrfContracts, vrfKey, env, err = SetupVRFV2PlusForExistingEnv(t, envConfig, l) + vrfContracts, vrfKey, env, sethClient, err = SetupVRFV2PlusForExistingEnv(t, envConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for Existing env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for Existing env", err) } } else { - vrfContracts, vrfKey, env, nodeTypeToNode, err = SetupVRFV2PlusForNewEnv(ctx, t, envConfig, newEnvConfig, l) + vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, err = SetupVRFV2PlusForNewEnv(ctx, t, envConfig, newEnvConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for New env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for New env", err) } } - return env, vrfContracts, vrfKey, nodeTypeToNode, nil + + return env, vrfContracts, vrfKey, nodeTypeToNode, sethClient, nil } func SetupVRFV2PlusForNewEnv( @@ -387,29 +381,26 @@ func SetupVRFV2PlusForNewEnv( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { network, err := actions.EthereumNetworkConfigFromConfig(l, &envConfig.TestConfig) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2Plus", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2Plus", err) } - env, err := vrfcommon.BuildNewCLEnvForVRF(t, envConfig, newEnvConfig, network) + env, sethClient, err := vrfcommon.BuildNewCLEnvForVRF(l, t, envConfig, newEnvConfig, network) if err != nil { - return nil, nil, nil, nil, err - } - sethClient, err := env.GetSethClient(envConfig.ChainID) - if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } mockETHLinkFeed, err := contracts.DeployVRFMockETHLINKFeed(sethClient, big.NewInt(*envConfig.TestConfig.VRFv2Plus.General.LinkNativeFeedResponse)) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) } linkToken, err := contracts.DeployLinkTokenContract(l, sethClient) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) } vrfContracts, vrfKey, nodeTypeToNode, err := SetupVRFV2_5Environment( ctx, + sethClient, env, envConfig.ChainID, newEnvConfig.NodesToCreate, @@ -420,45 +411,49 @@ func SetupVRFV2PlusForNewEnv( l, ) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2_5 env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2_5 env", err) } - return vrfContracts, vrfKey, env, nodeTypeToNode, nil + + return vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, nil } -func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, error) { +func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, *seth.Client, error) { commonExistingEnvConfig := envConfig.TestConfig.VRFv2Plus.ExistingEnvConfig.ExistingEnvConfig env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) } - sethClient, err := env.GetSethClient(envConfig.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err + } + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) + if err != nil { + return nil, nil, nil, nil, err } coordinator, err := contracts.LoadVRFCoordinatorV2_5(sethClient, *commonExistingEnvConfig.CoordinatorAddress) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2_5", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2_5", err) } linkToken, err := contracts.LoadLinkTokenContract(l, sethClient, common.HexToAddress(*commonExistingEnvConfig.LinkAddress)) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) } err = vrfcommon.FundNodesIfNeeded(testcontext.Get(t), commonExistingEnvConfig, sethClient, l) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStoreAddress, err := coordinator.GetBlockHashStoreAddress(testcontext.Get(t)) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStore, err := contracts.LoadBlockHashStore(sethClient, blockHashStoreAddress.String()) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) } vrfContracts := &vrfcommon.VRFContracts{ CoordinatorV2Plus: coordinator, @@ -471,13 +466,12 @@ func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig EncodedProvingKey: [2]*big.Int{}, KeyHash: common.HexToHash(*commonExistingEnvConfig.KeyHash), } - return vrfContracts, vrfKey, env, nil + return vrfContracts, vrfKey, env, sethClient, nil } func SetupSubsAndConsumersForExistingEnv( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, linkToken contracts.LinkToken, numberOfConsumerContractsToDeployAndAddToSub int, @@ -490,17 +484,12 @@ func SetupSubsAndConsumersForExistingEnv( consumers []contracts.VRFv2PlusLoadTestConsumer err error ) - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } if *testConfig.VRFv2Plus.General.UseExistingEnv { commonExistingEnvConfig := testConfig.VRFv2Plus.ExistingEnvConfig.ExistingEnvConfig if *commonExistingEnvConfig.CreateFundSubsAndAddConsumers { consumers, subIDs, err = SetupNewConsumersAndSubs( ctx, - env, - chainID, + sethClient, coordinator, testConfig, linkToken, @@ -527,8 +516,7 @@ func SetupSubsAndConsumersForExistingEnv( } else { consumers, subIDs, err = SetupNewConsumersAndSubs( ctx, - env, - chainID, + sethClient, coordinator, testConfig, linkToken, diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index b06c2564a88..a0dcad721f3 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -20,7 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -145,7 +145,7 @@ func TestAutomationBenchmark(t *testing.T) { l.Info().Str("Namespace", testEnvironment.Cfg.Namespace).Msg("Connected to Keepers Benchmark Environment") testNetwork := seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, benchmarkNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(&config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetAutoFixFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(&config, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetAutoFixFn) require.NoError(t, err, "Error getting Seth client") registryVersions := addRegistry(&config) @@ -193,7 +193,7 @@ func TestAutomationBenchmark(t *testing.T) { }, ) t.Cleanup(func() { - if err = actions_seth.TeardownRemoteSuite(keeperBenchmarkTest.TearDownVals(t)); err != nil { + if err = actions.TeardownRemoteSuite(keeperBenchmarkTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") } }) diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index fcbf8f5a471..a6267138d21 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -245,24 +244,24 @@ func TestAutomationChaos(t *testing.T) { network = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, network, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(&config, network, actions_seth.OneEphemeralKeysLiveTestnetAutoFixFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(&config, network, seth_utils.OneEphemeralKeysLiveTestnetAutoFixFn) require.NoError(t, err, "Error creating seth client") // Register cleanup for any test t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) require.NoError(t, err, "Error tearing down environment") }) - txCost, err := actions_seth.EstimateCostForChainlinkOperations(l, chainClient, network, 1000) + txCost, err := actions.EstimateCostForChainlinkOperations(l, chainClient, network, 1000) require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), txCost) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), txCost) require.NoError(t, err, "Error funding Chainlink nodes") linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) require.NoError(t, err, "Error deploying LINK token") - registry, registrar := actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, chainClient, rv, @@ -287,8 +286,8 @@ func TestAutomationChaos(t *testing.T) { } require.NoError(t, err, "Error setting OCR config") - consumersConditional, upkeepidsConditional := actions_seth.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) - consumersLogtrigger, upkeepidsLogtrigger := actions_seth.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) + consumersConditional, upkeepidsConditional := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) + consumersLogtrigger, upkeepidsLogtrigger := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) consumers := append(consumersConditional, consumersLogtrigger...) upkeepIDs := append(upkeepidsConditional, upkeepidsLogtrigger...) diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go index dfd1efaefe0..2800e763f1c 100644 --- a/integration-tests/chaos/ocr2vrf_chaos_test.go +++ b/integration-tests/chaos/ocr2vrf_chaos_test.go @@ -20,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -157,7 +156,7 @@ func TestOCR2VRFChaos(t *testing.T) { require.NoError(t, err) testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(testconfig, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testconfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -166,7 +165,7 @@ func TestOCR2VRFChaos(t *testing.T) { require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &testconfig) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &testconfig) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 9f7dea3c258..99cc9869849 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -24,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -168,14 +167,14 @@ func TestOCRChaos(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(cfg.GetNetworkConfig())[0] network = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, network, *testEnvironment) - seth, err := actions_seth.GetChainClient(&cfg, network) + seth, err := seth_utils.GetChainClient(&cfg, network) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") bootstrapNode, workerNodes := chainlinkNodes[0], chainlinkNodes[1:] t.Cleanup(func() { - err := actions_seth.TeardownRemoteSuite(t, seth, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &cfg) + err := actions.TeardownRemoteSuite(t, seth, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &cfg) require.NoError(t, err, "Error tearing down environment") }) @@ -185,10 +184,10 @@ func TestOCRChaos(t *testing.T) { linkContract, err := contracts.DeployLinkTokenContract(l, seth) require.NoError(t, err, "Error deploying link token contract") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), big.NewFloat(10)) + err = actions.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), big.NewFloat(10)) require.NoError(t, err) - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, seth, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, seth, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err) err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, ms, fmt.Sprint(seth.ChainID)) require.NoError(t, err) diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go deleted file mode 100644 index dab50e7aab5..00000000000 --- a/integration-tests/contracts/contract_deployer.go +++ /dev/null @@ -1,1898 +0,0 @@ -package contracts - -import ( - "context" - "errors" - "fmt" - "math/big" - "strings" - "time" - - "github.com/smartcontractkit/chainlink-testing-framework/networks" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/arbitrum_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" - automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic" - registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" - registrylogica22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_2" - registrylogicb22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_2" - registry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_wrapper_2_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_module_base" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_billing_registry_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_oracle_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper_mock" - iregistry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" - ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_chain_module" - iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic2_0" - registrylogica21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1" - registrylogicb21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" - registry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_aggregator_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/optimism_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/scroll_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" -) - -// ContractDeployer is an interface for abstracting the contract deployment methods across network implementations -type ContractDeployer interface { - DeployAPIConsumer(linkAddr string) (APIConsumer, error) - DeployOracle(linkAddr string) (Oracle, error) - DeployFlags(rac string) (Flags, error) - DeployFluxAggregatorContract(linkAddr string, fluxOptions FluxAggregatorOptions) (FluxAggregator, error) - DeployLinkTokenContract() (LinkToken, error) - DeployWERC20Mock() (WERC20Mock, error) - LoadLinkToken(address common.Address) (LinkToken, error) - DeployOffChainAggregator(linkAddr string, offchainOptions OffchainOptions) (OffchainAggregator, error) - LoadOffChainAggregator(address *common.Address) (OffchainAggregator, error) - DeployMockETHLINKFeed(answer *big.Int) (MockETHLINKFeed, error) - LoadETHLINKFeed(address common.Address) (MockETHLINKFeed, error) - DeployMockGasFeed(answer *big.Int) (MockGasFeed, error) - LoadGasFeed(address common.Address) (MockGasFeed, error) - DeployKeeperRegistrar(registryVersion eth_contracts.KeeperRegistryVersion, linkAddr string, registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) - LoadKeeperRegistrar(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistrar, error) - DeployUpkeepTranscoder() (UpkeepTranscoder, error) - LoadUpkeepTranscoder(address common.Address) (UpkeepTranscoder, error) - DeployKeeperRegistry(opts *KeeperRegistryOpts) (KeeperRegistry, error) - LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) - DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) - DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) - DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) - DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) - DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error) - DeployKeeperConsumerPerformance( - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn *big.Int, - ) (KeeperConsumerPerformance, error) - DeployKeeperConsumerBenchmark() (AutomationConsumerBenchmark, error) - LoadKeeperConsumerBenchmark(address common.Address) (AutomationConsumerBenchmark, error) - DeployKeeperPerformDataChecker(expectedData []byte) (KeeperPerformDataChecker, error) - DeployUpkeepCounter(testRange *big.Int, interval *big.Int) (UpkeepCounter, error) - DeployUpkeepPerformCounterRestrictive(testRange *big.Int, averageEligibilityCadence *big.Int) (UpkeepPerformCounterRestrictive, error) - DeployOperatorFactory(linkAddr string) (OperatorFactory, error) - DeployStaking(params eth_contracts.StakingPoolConstructorParams) (Staking, error) - DeployFunctionsLoadTestClient(router string) (FunctionsLoadTestClient, error) - DeployFunctionsOracleEventsMock() (FunctionsOracleEventsMock, error) - DeployFunctionsBillingRegistryEventsMock() (FunctionsBillingRegistryEventsMock, error) - DeployStakingEventsMock() (StakingEventsMock, error) - DeployFunctionsV1EventsMock() (FunctionsV1EventsMock, error) - DeployOffchainAggregatorEventsMock() (OffchainAggregatorEventsMock, error) - DeployMockAggregatorProxy(aggregatorAddr string) (MockAggregatorProxy, error) - DeployOffchainAggregatorV2(linkAddr string, offchainOptions OffchainOptions) (OffchainAggregatorV2, error) - LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) - DeployKeeperRegistryCheckUpkeepGasUsageWrapper(keeperRegistryAddr string) (KeeperRegistryCheckUpkeepGasUsageWrapper, error) - DeployKeeperRegistry11Mock() (KeeperRegistry11Mock, error) - DeployKeeperRegistrar12Mock() (KeeperRegistrar12Mock, error) - DeployKeeperGasWrapperMock() (KeeperGasWrapperMock, error) - DeployMercuryVerifierContract(verifierProxyAddr common.Address) (MercuryVerifier, error) - DeployMercuryVerifierProxyContract(accessControllerAddr common.Address) (MercuryVerifierProxy, error) - DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error) - DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error) - DeployLogEmitterContract() (LogEmitter, error) - DeployMultiCallContract() (common.Address, error) -} - -// NewContractDeployer returns an instance of a contract deployer based on the client type -func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) (ContractDeployer, error) { - switch clientImpl := bcClient.Get().(type) { - case *blockchain.EthereumClient: - return NewEthereumContractDeployer(clientImpl, logger), nil - case *blockchain.KlaytnClient: - return &KlaytnContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.MetisClient: - return &MetisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.ArbitrumClient: - return &MetisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.OptimismClient: - return &OptimismContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.RSKClient: - return &RSKContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.PolygonClient: - return &PolygonContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.CeloClient: - return &CeloContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.QuorumClient: - return &QuorumContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.BSCClient: - return &BSCContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.ScrollClient: - return &ScrollContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.PolygonZkEvmClient: - return &PolygonZkEvmContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.LineaClient: - return &LineaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.FantomClient: - return &FantomContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.KromaClient: - return &KromaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.WeMixClient: - return &WeMixContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.GnosisClient: - return &GnosisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - } - return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer") -} - -// EthereumContractDeployer provides the implementations for deploying ETH (EVM) based contracts -type EthereumContractDeployer struct { - client blockchain.EVMClient - l zerolog.Logger -} - -// KlaytnContractDeployer wraps ethereum contract deployments for Klaytn -type KlaytnContractDeployer struct { - *EthereumContractDeployer -} - -// MetisContractDeployer wraps ethereum contract deployments for Metis -type MetisContractDeployer struct { - *EthereumContractDeployer -} - -// ArbitrumContractDeployer wraps for Arbitrum -type ArbitrumContractDeployer struct { - *EthereumContractDeployer -} - -// OptimismContractDeployer wraps for Optimism -type OptimismContractDeployer struct { - *EthereumContractDeployer -} - -// RSKContractDeployer wraps for RSK -type RSKContractDeployer struct { - *EthereumContractDeployer -} - -type PolygonContractDeployer struct { - *EthereumContractDeployer -} - -type CeloContractDeployer struct { - *EthereumContractDeployer -} - -type QuorumContractDeployer struct { - *EthereumContractDeployer -} - -type BSCContractDeployer struct { - *EthereumContractDeployer -} - -type ScrollContractDeployer struct { - *EthereumContractDeployer -} - -type PolygonZkEvmContractDeployer struct { - *EthereumContractDeployer -} - -type LineaContractDeployer struct { - *EthereumContractDeployer -} - -type FantomContractDeployer struct { - *EthereumContractDeployer -} - -type KromaContractDeployer struct { - *EthereumContractDeployer -} - -type WeMixContractDeployer struct { - *EthereumContractDeployer -} - -type GnosisContractDeployer struct { - *EthereumContractDeployer -} - -// NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer -func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer { - return &EthereumContractDeployer{ - client: ethClient, - l: logger, - } -} - -// DefaultFluxAggregatorOptions produces some basic defaults for a flux aggregator contract -func DefaultFluxAggregatorOptions() FluxAggregatorOptions { - return FluxAggregatorOptions{ - PaymentAmount: big.NewInt(1), - Timeout: uint32(30), - MinSubValue: big.NewInt(0), - MaxSubValue: big.NewInt(1000000000000), - Decimals: uint8(0), - Description: "Test Flux Aggregator", - } -} - -// DeployFlags deploys flags contract -func (e *EthereumContractDeployer) DeployFlags( - rac string, -) (Flags, error) { - address, _, instance, err := e.client.DeployContract("Flags", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - racAddr := common.HexToAddress(rac) - return flags_wrapper.DeployFlags(auth, backend, racAddr) - }) - if err != nil { - return nil, err - } - return &EthereumFlags{ - client: e.client, - flags: instance.(*flags_wrapper.Flags), - address: address, - }, nil -} - -// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain -func (e *EthereumContractDeployer) DeployFluxAggregatorContract( - linkAddr string, - fluxOptions FluxAggregatorOptions, -) (FluxAggregator, error) { - address, _, instance, err := e.client.DeployContract("Flux Aggregator", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return flux_aggregator_wrapper.DeployFluxAggregator(auth, - backend, - la, - fluxOptions.PaymentAmount, - fluxOptions.Timeout, - fluxOptions.Validator, - fluxOptions.MinSubValue, - fluxOptions.MaxSubValue, - fluxOptions.Decimals, - fluxOptions.Description) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFluxAggregator{ - client: e.client, - fluxAggregator: instance.(*flux_aggregator_wrapper.FluxAggregator), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployStaking(params eth_contracts.StakingPoolConstructorParams) (Staking, error) { - stakingAddress, _, instance, err := e.client.DeployContract("Staking", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployStaking(auth, backend, params) - }) - if err != nil { - return nil, err - } - return &EthereumStaking{ - client: e.client, - staking: instance.(*eth_contracts.Staking), - address: stakingAddress, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsLoadTestClient(router string) (FunctionsLoadTestClient, error) { - address, _, instance, err := e.client.DeployContract("FunctionsLoadTestClient", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_load_test_client.DeployFunctionsLoadTestClient(auth, backend, common.HexToAddress(router)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsLoadTestClient{ - client: e.client, - instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), - address: *address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsOracleEventsMock() (FunctionsOracleEventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsOracleEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_oracle_events_mock.DeployFunctionsOracleEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumFunctionsOracleEventsMock{ - client: e.client, - eventsMock: instance.(*functions_oracle_events_mock.FunctionsOracleEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsBillingRegistryEventsMock() (FunctionsBillingRegistryEventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsBillingRegistryEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_billing_registry_events_mock.DeployFunctionsBillingRegistryEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumFunctionsBillingRegistryEventsMock{ - client: e.client, - eventsMock: instance.(*functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployStakingEventsMock() (StakingEventsMock, error) { - address, _, instance, err := e.client.DeployContract("StakingEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployStakingEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumStakingEventsMock{ - client: e.client, - eventsMock: instance.(*eth_contracts.StakingEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsV1EventsMock() (FunctionsV1EventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsV1EventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_v1_events_mock.DeployFunctionsV1EventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsV1EventsMock{ - client: e.client, - eventsMock: instance.(*functions_v1_events_mock.FunctionsV1EventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperRegistry11Mock() (KeeperRegistry11Mock, error) { - address, _, instance, err := e.client.DeployContract("KeeperRegistry11Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_1_mock.DeployKeeperRegistryMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry11Mock{ - client: e.client, - registryMock: instance.(*keeper_registry_wrapper1_1_mock.KeeperRegistryMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperRegistrar12Mock() (KeeperRegistrar12Mock, error) { - address, _, instance, err := e.client.DeployContract("KeeperRegistrar12Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper1_2_mock.DeployKeeperRegistrarMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar12Mock{ - client: e.client, - registrarMock: instance.(*keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperGasWrapperMock() (KeeperGasWrapperMock, error) { - address, _, instance, err := e.client.DeployContract("KeeperGasWrapperMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return gas_wrapper_mock.DeployKeeperRegistryCheckUpkeepGasUsageWrapperMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperGasWrapperMock{ - client: e.client, - gasWrapperMock: instance.(*gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployOffchainAggregatorEventsMock() (OffchainAggregatorEventsMock, error) { - address, _, instance, err := e.client.DeployContract("OffchainAggregatorEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployOffchainAggregatorEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumOffchainAggregatorEventsMock{ - client: e.client, - eventsMock: instance.(*eth_contracts.OffchainAggregatorEventsMock), - address: address, - }, nil -} - -// DeployLinkTokenContract deploys a Link Token contract to an EVM chain -func (e *EthereumContractDeployer) DeployLinkTokenContract() (LinkToken, error) { - linkTokenAddress, _, instance, err := e.client.DeployContract("LINK Token", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return link_token_interface.DeployLinkToken(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - if err != nil { - return nil, err - } - - return &LegacyEthereumLinkToken{ - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - address: *linkTokenAddress, - l: e.l, - }, err -} - -// LoadLinkToken returns deployed on given address EthereumLinkToken -func (e *EthereumContractDeployer) LoadLinkToken(address common.Address) (LinkToken, error) { - instance, err := e.client.LoadContract("LinkToken", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return link_token_interface.NewLinkToken(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumLinkToken{ - address: address, - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) NewLinkTokenContract(address common.Address) (LinkToken, error) { - return e.LoadLinkToken(address) -} - -// DefaultOffChainAggregatorOptions returns some base defaults for deploying an OCR contract -func DefaultOffChainAggregatorOptions() OffchainOptions { - return OffchainOptions{ - MaximumGasPrice: uint32(3000), - ReasonableGasPrice: uint32(10), - MicroLinkPerEth: uint32(500), - LinkGweiPerObservation: uint32(500), - LinkGweiPerTransmission: uint32(500), - MinimumAnswer: big.NewInt(1), - MaximumAnswer: big.NewInt(50000000000000000), - Decimals: 8, - Description: "Test OCR", - } -} - -// DefaultOffChainAggregatorConfig returns some base defaults for configuring an OCR contract -func DefaultOffChainAggregatorConfig(numberNodes int) OffChainAggregatorConfig { - if numberNodes <= 4 { - log.Err(fmt.Errorf("insufficient number of nodes (%d) supplied for OCR, need at least 5", numberNodes)). - Int("Number Chainlink Nodes", numberNodes). - Msg("You likely need more chainlink nodes to properly configure OCR, try 5 or more.") - } - s := []int{1} - // First node's stage already inputted as a 1 in line above, so numberNodes-1. - for i := 0; i < numberNodes-1; i++ { - s = append(s, 2) - } - return OffChainAggregatorConfig{ - AlphaPPB: 1, - DeltaC: time.Minute * 60, - DeltaGrace: time.Second * 12, - DeltaProgress: time.Second * 35, - DeltaStage: time.Second * 60, - DeltaResend: time.Second * 17, - DeltaRound: time.Second * 30, - RMax: 6, - S: s, - N: numberNodes, - F: 1, - OracleIdentities: []ocrConfigHelper.OracleIdentityExtra{}, - } -} - -// DeployOffChainAggregator deploys the offchain aggregation contract to the EVM chain -func (e *EthereumContractDeployer) DeployOffChainAggregator( - linkAddr string, - offchainOptions OffchainOptions, -) (OffchainAggregator, error) { - address, _, instance, err := e.client.DeployContract("OffChain Aggregator", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return offchainaggregator.DeployOffchainAggregator(auth, - backend, - offchainOptions.MaximumGasPrice, - offchainOptions.ReasonableGasPrice, - offchainOptions.MicroLinkPerEth, - offchainOptions.LinkGweiPerObservation, - offchainOptions.LinkGweiPerTransmission, - la, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregator{ - client: e.client, - ocr: instance.(*offchainaggregator.OffchainAggregator), - address: address, - l: e.l, - }, err -} - -// LoadOffChainAggregator loads an already deployed offchain aggregator contract -func (e *EthereumContractDeployer) LoadOffChainAggregator(address *common.Address) (OffchainAggregator, error) { - instance, err := e.client.LoadContract("OffChainAggregator", *address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return offchainaggregator.NewOffchainAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregator{ - address: address, - client: e.client, - ocr: instance.(*offchainaggregator.OffchainAggregator), - l: e.l, - }, err -} - -// DeployAPIConsumer deploys api consumer for oracle -func (e *EthereumContractDeployer) DeployAPIConsumer(linkAddr string) (APIConsumer, error) { - addr, _, instance, err := e.client.DeployContract("TestAPIConsumer", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return test_api_consumer_wrapper.DeployTestAPIConsumer(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAPIConsumer{ - address: addr, - client: e.client, - consumer: instance.(*test_api_consumer_wrapper.TestAPIConsumer), - }, err -} - -// DeployOracle deploys oracle for consumer test -func (e *EthereumContractDeployer) DeployOracle(linkAddr string) (Oracle, error) { - addr, _, instance, err := e.client.DeployContract("Oracle", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return oracle_wrapper.DeployOracle(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOracle{ - address: addr, - client: e.client, - oracle: instance.(*oracle_wrapper.Oracle), - }, err -} - -func (e *EthereumContractDeployer) DeployMockETHLINKFeed(answer *big.Int) (MockETHLINKFeed, error) { - address, _, instance, err := e.client.DeployContract("MockETHLINKAggregator", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_ethlink_aggregator_wrapper.DeployMockETHLINKAggregator(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), answer) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockETHLINKFeed{ - client: e.client, - feed: instance.(*mock_ethlink_aggregator_wrapper.MockETHLINKAggregator), - address: address, - }, err -} - -// LoadETHLINKFeed returns deployed on given address EthereumMockETHLINKFeed -func (e *EthereumContractDeployer) LoadETHLINKFeed(address common.Address) (MockETHLINKFeed, error) { - instance, err := e.client.LoadContract("MockETHLINKFeed", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockETHLINKFeed{ - address: &address, - client: e.client, - feed: instance.(*mock_ethlink_aggregator_wrapper.MockETHLINKAggregator), - }, err -} - -func (e *EthereumContractDeployer) DeployMockGasFeed(answer *big.Int) (MockGasFeed, error) { - address, _, instance, err := e.client.DeployContract("MockGasFeed", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_gas_aggregator_wrapper.DeployMockGASAggregator(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), answer) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockGASFeed{ - client: e.client, - feed: instance.(*mock_gas_aggregator_wrapper.MockGASAggregator), - address: address, - }, err -} - -// LoadGasFeed returns deployed on given address EthereumMockGASFeed -func (e *EthereumContractDeployer) LoadGasFeed(address common.Address) (MockGasFeed, error) { - instance, err := e.client.LoadContract("MockETHLINKFeed", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return mock_gas_aggregator_wrapper.NewMockGASAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockGASFeed{ - address: &address, - client: e.client, - feed: instance.(*mock_gas_aggregator_wrapper.MockGASAggregator), - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepTranscoder() (UpkeepTranscoder, error) { - address, _, instance, err := e.client.DeployContract("UpkeepTranscoder", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_transcoder.DeployUpkeepTranscoder(opts, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumUpkeepTranscoder{ - client: e.client, - transcoder: instance.(*upkeep_transcoder.UpkeepTranscoder), - address: address, - }, err -} - -func (e *EthereumContractDeployer) LoadUpkeepTranscoder(address common.Address) (UpkeepTranscoder, error) { - instance, err := e.client.LoadContract("UpkeepTranscoder", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return upkeep_transcoder.NewUpkeepTranscoder(address, backend) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumUpkeepTranscoder{ - client: e.client, - transcoder: instance.(*upkeep_transcoder.UpkeepTranscoder), - address: &address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistrar(registryVersion eth_contracts.KeeperRegistryVersion, linkAddr string, - registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) { - - if registryVersion == eth_contracts.RegistryVersion_2_0 { - // deploy registrar 2.0 - address, _, instance, err := e.client.DeployContract("KeeperRegistrar", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper2_0.DeployKeeperRegistrar(opts, wrappers.MustNewWrappedContractBackend(e.client, nil), common.HexToAddress(linkAddr), registrarSettings.AutoApproveConfigType, - registrarSettings.AutoApproveMaxAllowed, common.HexToAddress(registrarSettings.RegistryAddr), registrarSettings.MinLinkJuels) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar20: instance.(*keeper_registrar_wrapper2_0.KeeperRegistrar), - address: address, - }, err - } else if registryVersion == eth_contracts.RegistryVersion_2_1 || registryVersion == eth_contracts.RegistryVersion_2_2 { // both 2.1 and 2.2 registry use registrar 2.1 - // deploy registrar 2.1 - address, _, instance, err := e.client.DeployContract("AutomationRegistrar", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - // set default TriggerType to 0(conditional), AutoApproveConfigType to 2(auto approve enabled), AutoApproveMaxAllowed to 1000 - triggerConfigs := []registrar21.AutomationRegistrar21InitialTriggerConfig{ - {TriggerType: 0, AutoApproveType: registrarSettings.AutoApproveConfigType, - AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, - {TriggerType: 1, AutoApproveType: registrarSettings.AutoApproveConfigType, - AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, - } - - return registrar21.DeployAutomationRegistrar( - opts, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(linkAddr), - common.HexToAddress(registrarSettings.RegistryAddr), - registrarSettings.MinLinkJuels, - triggerConfigs) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar21: instance.(*registrar21.AutomationRegistrar), - address: address, - }, err - } - // non OCR registrar - address, _, instance, err := e.client.DeployContract("KeeperRegistrar", func( - opts *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper1_2.DeployKeeperRegistrar(opts, backend, common.HexToAddress(linkAddr), registrarSettings.AutoApproveConfigType, - registrarSettings.AutoApproveMaxAllowed, common.HexToAddress(registrarSettings.RegistryAddr), registrarSettings.MinLinkJuels) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar: instance.(*keeper_registrar_wrapper1_2.KeeperRegistrar), - address: address, - }, err -} - -// LoadKeeperRegistrar returns deployed on given address EthereumKeeperRegistrar -func (e *EthereumContractDeployer) LoadKeeperRegistrar(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistrar, error) { - if registryVersion == eth_contracts.RegistryVersion_1_1 || registryVersion == eth_contracts.RegistryVersion_1_2 || - registryVersion == eth_contracts.RegistryVersion_1_3 { - instance, err := e.client.LoadContract("KeeperRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registrar_wrapper1_2.NewKeeperRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar: instance.(*keeper_registrar_wrapper1_2.KeeperRegistrar), - }, err - } else if registryVersion == eth_contracts.RegistryVersion_2_0 { - instance, err := e.client.LoadContract("KeeperRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registrar_wrapper2_0.NewKeeperRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar20: instance.(*keeper_registrar_wrapper2_0.KeeperRegistrar), - }, err - } - instance, err := e.client.LoadContract("AutomationRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return registrar21.NewAutomationRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar21: instance.(*registrar21.AutomationRegistrar), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistry( - opts *KeeperRegistryOpts, -) (KeeperRegistry, error) { - var mode uint8 - switch e.client.GetChainID().Int64() { - //Arbitrum payment model - case networks.ArbitrumMainnet.ChainID, networks.ArbitrumSepolia.ChainID: - mode = uint8(1) - //Optimism payment model - case networks.OptimismMainnet.ChainID, networks.OptimismSepolia.ChainID: - mode = uint8(2) - //Base - case networks.BaseMainnet.ChainID, networks.BaseSepolia.ChainID: - mode = uint8(2) - default: - mode = uint8(0) - } - registryGasOverhead := big.NewInt(80000) - switch opts.RegistryVersion { - case eth_contracts.RegistryVersion_1_0, eth_contracts.RegistryVersion_1_1: - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_1.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - opts.Settings.PaymentPremiumPPB, - opts.Settings.FlatFeeMicroLINK, - opts.Settings.BlockCountPerTurn, - opts.Settings.CheckGasLimit, - opts.Settings.StalenessSeconds, - opts.Settings.GasCeilingMultiplier, - opts.Settings.FallbackGasPrice, - opts.Settings.FallbackLinkPrice, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_1, - registry1_1: instance.(*keeper_registry_wrapper1_1.KeeperRegistry), - registry1_2: nil, - registry1_3: nil, - address: address, - }, err - case eth_contracts.RegistryVersion_1_2: - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_2.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_2, - registry1_1: nil, - registry1_2: instance.(*keeper_registry_wrapper1_2.KeeperRegistry), - registry1_3: nil, - address: address, - }, err - case eth_contracts.RegistryVersion_1_3: - logicAddress, _, _, err := e.client.DeployContract("KeeperRegistryLogic1_3", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_logic1_3.DeployKeeperRegistryLogic( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, // Default payment model - registryGasOverhead, // Registry gas overhead - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - ) - }) - if err != nil { - return nil, err - } - err = e.client.WaitForEvents() - if err != nil { - return nil, err - } - - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_3", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_3.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *logicAddress, - keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_3, - registry1_1: nil, - registry1_2: nil, - registry1_3: instance.(*keeper_registry_wrapper1_3.KeeperRegistry), - address: address, - }, err - case eth_contracts.RegistryVersion_2_0: - logicAddress, _, _, err := e.client.DeployContract("KeeperRegistryLogic2_0", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_logic2_0.DeployKeeperRegistryLogic( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, // Default payment model - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - ) - }) - if err != nil { - return nil, err - } - err = e.client.WaitForEvents() - if err != nil { - return nil, err - } - - address, _, instance, err := e.client.DeployContract("KeeperRegistry2_0", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return keeper_registry_wrapper2_0.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *logicAddress, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_0, - registry2_0: instance.(*keeper_registry_wrapper2_0.KeeperRegistry), - address: address, - }, err - - case eth_contracts.RegistryVersion_2_1: - automationForwarderLogicAddr, err := deployAutomationForwarderLogic(e.client) - if err != nil { - return nil, err - } - - registryLogicBAddr, _, _, err := e.client.DeployContract("KeeperRegistryLogicB2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogicb21.DeployKeeperRegistryLogicB( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - *automationForwarderLogicAddr, - ) - }) - if err != nil { - return nil, err - } - - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryLogicAAddr, _, _, err := e.client.DeployContract("KeeperRegistryLogicA2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogica21.DeployKeeperRegistryLogicA( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicBAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - address, _, _, err := e.client.DeployContract("KeeperRegistry2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return registry21.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicAAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryMaster, err := iregistry21.NewIKeeperRegistryMaster( - *address, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_1, - registry2_1: registryMaster, - address: address, - }, err - case eth_contracts.RegistryVersion_2_2: - var chainModuleAddr *common.Address - var err error - chainId := e.client.GetChainID().Int64() - - if chainId == networks.ScrollMainnet.ChainID || chainId == networks.ScrollSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("ScrollModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return scroll_module.DeployScrollModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else if chainId == networks.ArbitrumMainnet.ChainID || chainId == networks.ArbitrumSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("ArbitrumModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return arbitrum_module.DeployArbitrumModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else if chainId == networks.OptimismMainnet.ChainID || chainId == networks.OptimismSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("OptimismModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return optimism_module.DeployOptimismModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else { - chainModuleAddr, _, _, err = e.client.DeployContract("ChainModuleBase", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return chain_module_base.DeployChainModuleBase(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } - if err != nil { - return nil, err - } - if err = e.client.WaitForEvents(); err != nil { - return nil, err - } - - automationForwarderLogicAddr, err := deployAutomationForwarderLogic(e.client) - if err != nil { - return nil, err - } - - var allowedReadOnlyAddress common.Address - if chainId == networks.PolygonZkEvmMainnet.ChainID || chainId == networks.PolygonZkEvmCardona.ChainID { - allowedReadOnlyAddress = common.HexToAddress("0x1111111111111111111111111111111111111111") - } else { - allowedReadOnlyAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") - } - registryLogicBAddr, _, _, err := e.client.DeployContract("AutomationRegistryLogicB2_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogicb22.DeployAutomationRegistryLogicB( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - *automationForwarderLogicAddr, - allowedReadOnlyAddress, - ) - }) - if err != nil { - return nil, err - } - - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryLogicAAddr, _, _, err := e.client.DeployContract("AutomationRegistryLogicA2_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogica22.DeployAutomationRegistryLogicA( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicBAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - address, _, _, err := e.client.DeployContract("AutomationRegistry2_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return registry22.DeployAutomationRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicAAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryMaster, err := iregistry22.NewIAutomationRegistryMaster( - *address, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - - chainModule, err := i_chain_module.NewIChainModule( - *chainModuleAddr, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_2, - registry2_2: registryMaster, - chainModule: chainModule, - address: address, - }, err - default: - return nil, fmt.Errorf("keeper registry version %d is not supported", opts.RegistryVersion) - } -} - -func deployAutomationForwarderLogic(client blockchain.EVMClient) (*common.Address, error) { - automationForwarderLogicAddr, _, _, err := client.DeployContract("automationForwarderLogic", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return automationForwarderLogic.DeployAutomationForwarderLogic(auth, backend) - }) - - if err != nil { - return nil, err - } - - if err := client.WaitForEvents(); err != nil { - return nil, err - } - return automationForwarderLogicAddr, nil -} - -// LoadKeeperRegistry returns deployed on given address EthereumKeeperRegistry -func (e *EthereumContractDeployer) LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) { - switch registryVersion { - case eth_contracts.RegistryVersion_1_1: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_1.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_1: instance.(*keeper_registry_wrapper1_1.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_1_2: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_2.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_2: instance.(*keeper_registry_wrapper1_2.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_1_3: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_3.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_3: instance.(*keeper_registry_wrapper1_3.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_0: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper2_0.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_0: instance.(*keeper_registry_wrapper2_0.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_1: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return ac.NewIAutomationV21PlusCommon(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_1: instance.(*iregistry21.IKeeperRegistryMaster), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_2: // why the contract name is not the same as the actual contract name? - instance, err := e.client.LoadContract("AutomationRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return iregistry22.NewIAutomationRegistryMaster(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_2: instance.(*iregistry22.IAutomationRegistryMaster), - version: registryVersion, - }, err - default: - return nil, fmt.Errorf("keeper registry version %d is not supported", registryVersion) - } -} - -func (e *EthereumContractDeployer) DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("KeeperConsumer", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_consumer_wrapper.DeployKeeperConsumer(auth, backend, updateInterval) - }) - if err != nil { - return nil, err - } - return &EthereumKeeperConsumer{ - client: e.client, - consumer: instance.(*keeper_consumer_wrapper.KeeperConsumer), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("LogUpkeepCounter", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return log_upkeep_counter_wrapper.DeployLogUpkeepCounter( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testInterval, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationLogCounterConsumer{ - client: e.client, - consumer: instance.(*log_upkeep_counter_wrapper.LogUpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("SimpleLogUpkeepCounter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return simple_log_upkeep_counter_wrapper.DeploySimpleLogUpkeepCounter( - auth, backend, isStreamsLookup, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationSimpleLogCounterConsumer{ - client: e.client, - consumer: instance.(*simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("StreamsLookupUpkeep", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return streams_lookup_upkeep_wrapper.DeployStreamsLookupUpkeep( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testRange, interval, useArbBlock, staging, verify, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationStreamsLookupUpkeepConsumer{ - client: e.client, - consumer: instance.(*streams_lookup_upkeep_wrapper.StreamsLookupUpkeep), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("LogTriggeredStreamsLookupUpkeep", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return log_triggered_streams_lookup_wrapper.DeployLogTriggeredStreamsLookup( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), false, false, false, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer{ - client: e.client, - consumer: instance.(*log_triggered_streams_lookup_wrapper.LogTriggeredStreamsLookup), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepCounter(testRange *big.Int, interval *big.Int) (UpkeepCounter, error) { - address, _, instance, err := e.client.DeployContract("UpkeepCounter", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_counter_wrapper.DeployUpkeepCounter(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testRange, interval) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumUpkeepCounter{ - client: e.client, - consumer: instance.(*upkeep_counter_wrapper.UpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepPerformCounterRestrictive(testRange *big.Int, averageEligibilityCadence *big.Int) (UpkeepPerformCounterRestrictive, error) { - address, _, instance, err := e.client.DeployContract("UpkeepPerformCounterRestrictive", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_perform_counter_restrictive_wrapper.DeployUpkeepPerformCounterRestrictive(auth, backend, testRange, averageEligibilityCadence) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumUpkeepPerformCounterRestrictive{ - client: e.client, - consumer: instance.(*upkeep_perform_counter_restrictive_wrapper.UpkeepPerformCounterRestrictive), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperConsumerPerformance( - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn *big.Int, -) (KeeperConsumerPerformance, error) { - address, _, instance, err := e.client.DeployContract("KeeperConsumerPerformance", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_consumer_performance_wrapper.DeployKeeperConsumerPerformance( - auth, - backend, - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperConsumerPerformance{ - client: e.client, - consumer: instance.(*keeper_consumer_performance_wrapper.KeeperConsumerPerformance), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperConsumerBenchmark() (AutomationConsumerBenchmark, error) { - address, _, instance, err := e.client.DeployContract("AutomationConsumerBenchmark", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return automation_consumer_benchmark.DeployAutomationConsumerBenchmark( - auth, - backend, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationConsumerBenchmark{ - client: e.client, - consumer: instance.(*automation_consumer_benchmark.AutomationConsumerBenchmark), - address: address, - }, err -} - -// LoadKeeperConsumerBenchmark returns deployed on given address EthereumAutomationConsumerBenchmark -func (e *EthereumContractDeployer) LoadKeeperConsumerBenchmark(address common.Address) (AutomationConsumerBenchmark, error) { - instance, err := e.client.LoadContract("AutomationConsumerBenchmark", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return automation_consumer_benchmark.NewAutomationConsumerBenchmark(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationConsumerBenchmark{ - address: &address, - client: e.client, - consumer: instance.(*automation_consumer_benchmark.AutomationConsumerBenchmark), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperPerformDataChecker(expectedData []byte) (KeeperPerformDataChecker, error) { - address, _, instance, err := e.client.DeployContract("PerformDataChecker", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return perform_data_checker_wrapper.DeployPerformDataChecker( - auth, - backend, - expectedData, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperPerformDataCheckerConsumer{ - client: e.client, - performDataChecker: instance.(*perform_data_checker_wrapper.PerformDataChecker), - address: address, - }, err -} - -// DeployOperatorFactory deploys operator factory contract -func (e *EthereumContractDeployer) DeployOperatorFactory(linkAddr string) (OperatorFactory, error) { - addr, _, instance, err := e.client.DeployContract("OperatorFactory", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return operator_factory.DeployOperatorFactory(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOperatorFactory{ - address: addr, - client: e.client, - operatorFactory: instance.(*operator_factory.OperatorFactory), - }, err -} - -// DeployMockAggregatorProxy deploys a mock aggregator proxy contract -func (e *EthereumContractDeployer) DeployMockAggregatorProxy(aggregatorAddr string) (MockAggregatorProxy, error) { - addr, _, instance, err := e.client.DeployContract("MockAggregatorProxy", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_aggregator_proxy.DeployMockAggregatorProxy(auth, backend, common.HexToAddress(aggregatorAddr)) - }) - if err != nil { - return nil, err - } - return &EthereumMockAggregatorProxy{ - address: addr, - client: e.client, - mockAggregatorProxy: instance.(*mock_aggregator_proxy.MockAggregatorProxy), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistryCheckUpkeepGasUsageWrapper(keeperRegistryAddr string) (KeeperRegistryCheckUpkeepGasUsageWrapper, error) { - addr, _, instance, err := e.client.DeployContract("KeeperRegistryCheckUpkeepGasUsageWrapper", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return gas_wrapper.DeployKeeperRegistryCheckUpkeepGasUsageWrapper(auth, backend, common.HexToAddress(keeperRegistryAddr)) - }) - if err != nil { - return nil, err - } - return &EthereumKeeperRegistryCheckUpkeepGasUsageWrapper{ - address: addr, - client: e.client, - gasUsageWrapper: instance.(*gas_wrapper.KeeperRegistryCheckUpkeepGasUsageWrapper), - }, err -} - -// DeployOffChainAggregator deploys the offchain aggregation contract to the EVM chain -func (e *EthereumContractDeployer) DeployOffchainAggregatorV2( - linkAddr string, - offchainOptions OffchainOptions, -) (OffchainAggregatorV2, error) { - address, _, instance, err := e.client.DeployContract("OffChain Aggregator v2", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return ocr2aggregator.DeployOCR2Aggregator( - auth, - backend, - la, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregatorV2{ - client: e.client, - contract: instance.(*ocr2aggregator.OCR2Aggregator), - address: address, - l: e.l, - }, err -} - -// LoadOffChainAggregatorV2 loads an already deployed offchain aggregator v2 contract -func (e *EthereumContractDeployer) LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) { - instance, err := e.client.LoadContract("OffChainAggregatorV2", *address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return ocr2aggregator.NewOCR2Aggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregatorV2{ - client: e.client, - contract: instance.(*ocr2aggregator.OCR2Aggregator), - address: address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryVerifierContract(verifierProxyAddr common.Address) (MercuryVerifier, error) { - address, _, instance, err := e.client.DeployContract("Mercury Verifier", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return verifier.DeployVerifier(auth, backend, verifierProxyAddr) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifier{ - client: e.client, - instance: instance.(*verifier.Verifier), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryVerifierProxyContract(accessControllerAddr common.Address) (MercuryVerifierProxy, error) { - address, _, instance, err := e.client.DeployContract("Mercury Verifier Proxy", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return verifier_proxy.DeployVerifierProxy(auth, backend, accessControllerAddr) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifierProxy{ - client: e.client, - instance: instance.(*verifier_proxy.VerifierProxy), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error) { - address, _, instance, err := e.client.DeployContract("Mercury Fee Manager", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return fee_manager.DeployFeeManager(auth, backend, linkAddress, nativeAddress, proxyAddress, rewardManagerAddress) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryFeeManager{ - client: e.client, - instance: instance.(*fee_manager.FeeManager), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error) { - address, _, instance, err := e.client.DeployContract("Mercury Reward Manager", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return reward_manager.DeployRewardManager(auth, backend, linkAddress) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryRewardManager{ - client: e.client, - instance: instance.(*reward_manager.RewardManager), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployWERC20Mock() (WERC20Mock, error) { - address, _, instance, err := e.client.DeployContract("WERC20 Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return werc20_mock.DeployWERC20Mock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumWERC20Mock{ - client: e.client, - instance: instance.(*werc20_mock.WERC20Mock), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployLogEmitterContract() (LogEmitter, error) { - address, _, instance, err := e.client.DeployContract("Log Emitter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return le.DeployLogEmitter(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyLogEmitterContract{ - client: e.client, - instance: instance.(*le.LogEmitter), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMultiCallContract() (common.Address, error) { - multiCallABI, err := abi.JSON(strings.NewReader(MultiCallABI)) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := e.client.DeployContract("MultiCall Contract", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - address, tx, contract, err := bind.DeployContract(auth, multiCallABI, common.FromHex(MultiCallBIN), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, contract, err - }) - if err != nil { - return common.Address{}, err - } - r, err := bind.WaitMined(context.Background(), e.client.DeployBackend(), tx) - if err != nil { - return common.Address{}, err - } - if r.Status != types.ReceiptStatusSuccessful { - return common.Address{}, fmt.Errorf("deploy multicall failed") - } - return *address, nil - -} diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go deleted file mode 100644 index 0cfa53b81f4..00000000000 --- a/integration-tests/contracts/contract_loader.go +++ /dev/null @@ -1,428 +0,0 @@ -package contracts - -import ( - "errors" - "fmt" - - "github.com/smartcontractkit/seth" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" -) - -// ContractLoader is an interface for abstracting the contract loading methods across network implementations -type ContractLoader interface { - LoadLINKToken(address string) (LinkToken, error) - LoadOperatorContract(address common.Address) (Operator, error) - LoadAuthorizedForwarder(address common.Address) (AuthorizedForwarder, error) - - /* functions 1_0_0 */ - LoadFunctionsCoordinator(addr string) (FunctionsCoordinator, error) - LoadFunctionsRouter(addr string) (FunctionsRouter, error) - LoadFunctionsLoadTestClient(addr string) (FunctionsLoadTestClient, error) - - // Mercury - LoadMercuryVerifier(addr common.Address) (MercuryVerifier, error) - LoadMercuryVerifierProxy(addr common.Address) (MercuryVerifierProxy, error) - LoadMercuryFeeManager(addr common.Address) (MercuryFeeManager, error) - LoadMercuryRewardManager(addr common.Address) (MercuryRewardManager, error) - - LoadWERC20Mock(addr common.Address) (WERC20Mock, error) -} - -// NewContractLoader returns an instance of a contract Loader based on the client type -func NewContractLoader(bcClient blockchain.EVMClient, logger zerolog.Logger) (ContractLoader, error) { - switch clientImpl := bcClient.Get().(type) { - case *blockchain.EthereumClient: - return NewEthereumContractLoader(clientImpl, logger), nil - case *blockchain.KlaytnClient: - return &KlaytnContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.MetisClient: - return &MetisContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.ArbitrumClient: - return &ArbitrumContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.PolygonClient: - return &PolygonContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.OptimismClient: - return &OptimismContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.PolygonZkEvmClient: - return &PolygonZkEvmContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.WeMixClient: - return &WeMixContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.LineaClient: - return &LineaContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.CeloClient: - return &CeloContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.ScrollClient: - return &ScrollContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.FantomClient: - return &FantomContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.BSCClient: - return &BSCContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.GnosisClient: - return &GnosisContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - } - return nil, errors.New("unknown blockchain client implementation for contract Loader, register blockchain client in NewContractLoader") -} - -// EthereumContractLoader provides the implementations for deploying ETH (EVM) based contracts -type EthereumContractLoader struct { - client blockchain.EVMClient - l zerolog.Logger -} - -// KlaytnContractLoader wraps ethereum contract deployments for Klaytn -type KlaytnContractLoader struct { - *EthereumContractLoader -} - -// MetisContractLoader wraps ethereum contract deployments for Metis -type MetisContractLoader struct { - *EthereumContractLoader -} - -// ArbitrumContractLoader wraps for Arbitrum -type ArbitrumContractLoader struct { - *EthereumContractLoader -} - -// PolygonContractLoader wraps for Polygon -type PolygonContractLoader struct { - *EthereumContractLoader -} - -// OptimismContractLoader wraps for Optimism -type OptimismContractLoader struct { - *EthereumContractLoader -} -type PolygonZkEvmContractLoader struct { - *EthereumContractLoader -} - -// PolygonZKEVMContractLoader wraps for Polygon zkEVM -type PolygonZKEVMContractLoader struct { - *EthereumContractLoader -} - -// WeMixContractLoader wraps for WeMix -type WeMixContractLoader struct { - *EthereumContractLoader -} - -// LineaContractLoader wraps for Linea -type LineaContractLoader struct { - *EthereumContractLoader -} - -// CeloContractLoader wraps for Celo -type CeloContractLoader struct { - *EthereumContractLoader -} - -// ScrollContractLoader wraps for Scroll -type ScrollContractLoader struct { - *EthereumContractLoader -} - -// FantomContractLoader wraps for Fantom -type FantomContractLoader struct { - *EthereumContractLoader -} - -// BSCContractLoader wraps for BSC -type BSCContractLoader struct { - *EthereumContractLoader -} - -// GnosisContractLoader wraps for Gnosis -type GnosisContractLoader struct { - *EthereumContractLoader -} - -// NewEthereumContractLoader returns an instantiated instance of the ETH contract Loader -func NewEthereumContractLoader(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractLoader { - return &EthereumContractLoader{ - client: ethClient, - l: logger, - } -} - -// LoadLINKToken returns deployed on given address LINK Token contract instance -func (e *EthereumContractLoader) LoadLINKToken(addr string) (LinkToken, error) { - instance, err := e.client.LoadContract("LINK Token", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return link_token_interface.NewLinkToken(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumLinkToken{ - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - address: common.HexToAddress(addr), - l: e.l, - }, err -} - -// LoadFunctionsCoordinator returns deployed on given address FunctionsCoordinator contract instance -func (e *EthereumContractLoader) LoadFunctionsCoordinator(addr string) (FunctionsCoordinator, error) { - instance, err := e.client.LoadContract("Functions Coordinator", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_coordinator.NewFunctionsCoordinator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsCoordinator{ - client: e.client, - instance: instance.(*functions_coordinator.FunctionsCoordinator), - address: common.HexToAddress(addr), - }, err -} - -// LoadFunctionsRouter returns deployed on given address FunctionsRouter contract instance -func (e *EthereumContractLoader) LoadFunctionsRouter(addr string) (FunctionsRouter, error) { - instance, err := e.client.LoadContract("Functions Router", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_router.NewFunctionsRouter(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsRouter{ - client: e.client, - instance: instance.(*functions_router.FunctionsRouter), - address: common.HexToAddress(addr), - l: e.l, - }, err -} - -// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance -func (e *EthereumContractLoader) LoadFunctionsLoadTestClient(addr string) (FunctionsLoadTestClient, error) { - instance, err := e.client.LoadContract("FunctionsLoadTestClient", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_load_test_client.NewFunctionsLoadTestClient(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsLoadTestClient{ - client: e.client, - instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), - address: common.HexToAddress(addr), - }, err -} - -// LoadOperatorContract returns deployed on given address Operator contract instance -func (e *EthereumContractLoader) LoadOperatorContract(address common.Address) (Operator, error) { - instance, err := e.client.LoadContract("Operator", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return operator_wrapper.NewOperator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOperator{ - address: address, - client: e.client, - operator: instance.(*operator_wrapper.Operator), - l: e.l, - }, err -} - -// LoadAuthorizedForwarder returns deployed on given address AuthorizedForwarder contract instance -func (e *EthereumContractLoader) LoadAuthorizedForwarder(address common.Address) (AuthorizedForwarder, error) { - instance, err := e.client.LoadContract("AuthorizedForwarder", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return authorized_forwarder.NewAuthorizedForwarder(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAuthorizedForwarder{ - address: address, - client: e.client, - authorizedForwarder: instance.(*authorized_forwarder.AuthorizedForwarder), - }, err -} - -// LoadMercuryVerifier returns Verifier contract deployed on given address -func (e *EthereumContractLoader) LoadMercuryVerifier(addr common.Address) (MercuryVerifier, error) { - instance, err := e.client.LoadContract("Mercury Verifier", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return verifier.NewVerifier(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifier{ - client: e.client, - instance: instance.(*verifier.Verifier), - address: addr, - }, err -} - -// LoadMercuryVerifierProxy returns VerifierProxy contract deployed on given address -func (e *EthereumContractLoader) LoadMercuryVerifierProxy(addr common.Address) (MercuryVerifierProxy, error) { - instance, err := e.client.LoadContract("Mercury Verifier Proxy", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return verifier_proxy.NewVerifierProxy(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifierProxy{ - client: e.client, - instance: instance.(*verifier_proxy.VerifierProxy), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadMercuryFeeManager(addr common.Address) (MercuryFeeManager, error) { - instance, err := e.client.LoadContract("Mercury Fee Manager", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return fee_manager.NewFeeManager(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryFeeManager{ - client: e.client, - instance: instance.(*fee_manager.FeeManager), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadMercuryRewardManager(addr common.Address) (MercuryRewardManager, error) { - instance, err := e.client.LoadContract("Mercury Reward Manager", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return reward_manager.NewRewardManager(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryRewardManager{ - client: e.client, - instance: instance.(*reward_manager.RewardManager), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadWERC20Mock(addr common.Address) (WERC20Mock, error) { - instance, err := e.client.LoadContract("WERC20 Mock", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return werc20_mock.NewWERC20Mock(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumWERC20Mock{ - client: e.client, - instance: instance.(*werc20_mock.WERC20Mock), - address: addr, - }, err -} - -func LoadVRFCoordinatorV2_5(seth *seth.Client, addr string) (VRFCoordinatorV2_5, error) { - address := common.HexToAddress(addr) - abi, err := vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.GetAbi() - if err != nil { - return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to get VRFCoordinatorV2_5 ABI: %w", err) - } - seth.ContractStore.AddABI("VRFCoordinatorV2_5", *abi) - seth.ContractStore.AddBIN("VRFCoordinatorV2_5", common.FromHex(vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.Bin)) - - contract, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to instantiate VRFCoordinatorV2_5 instance: %w", err) - } - - return &EthereumVRFCoordinatorV2_5{ - client: seth, - address: address, - coordinator: contract, - }, nil -} - -func LoadBlockHashStore(seth *seth.Client, addr string) (BlockHashStore, error) { - address := common.HexToAddress(addr) - abi, err := blockhash_store.BlockhashStoreMetaData.GetAbi() - if err != nil { - return &EthereumBlockhashStore{}, fmt.Errorf("failed to get BlockHashStore ABI: %w", err) - } - seth.ContractStore.AddABI("BlockHashStore", *abi) - seth.ContractStore.AddBIN("BlockHashStore", common.FromHex(blockhash_store.BlockhashStoreMetaData.Bin)) - - contract, err := blockhash_store.NewBlockhashStore(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumBlockhashStore{}, fmt.Errorf("failed to instantiate BlockHashStore instance: %w", err) - } - - return &EthereumBlockhashStore{ - client: seth, - address: &address, - blockHashStore: contract, - }, nil -} - -func LoadVRFv2PlusLoadTestConsumer(seth *seth.Client, addr string) (VRFv2PlusLoadTestConsumer, error) { - address := common.HexToAddress(addr) - abi, err := vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.GetAbi() - if err != nil { - return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to get VRFV2PlusLoadTestWithMetrics ABI: %w", err) - } - seth.ContractStore.AddABI("VRFV2PlusLoadTestWithMetrics", *abi) - seth.ContractStore.AddBIN("VRFV2PlusLoadTestWithMetrics", common.FromHex(vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.Bin)) - - contract, err := vrf_v2plus_load_test_with_metrics.NewVRFV2PlusLoadTestWithMetrics(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to instantiate VRFV2PlusLoadTestWithMetrics instance: %w", err) - } - - return &EthereumVRFv2PlusLoadTestConsumer{ - client: seth, - address: address, - consumer: contract, - }, nil -} diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index ec61ad68183..6d6c9108a4f 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -3,1322 +3,267 @@ package contracts import ( "context" "encoding/hex" + "errors" "fmt" "math/big" "strings" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" contractsethereum "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_billing_registry_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_oracle_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper_mock" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" iregistry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_aggregator_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) -// LegacyEthereumOracle oracle for "directrequest" job tests -type LegacyEthereumOracle struct { - address *common.Address - client blockchain.EVMClient - oracle *oracle_wrapper.Oracle -} - -func (e *LegacyEthereumOracle) Address() string { - return e.address.Hex() -} - -func (e *LegacyEthereumOracle) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ - To: e.address, - }) - if err != nil { - return err - } - return e.client.Fund(e.address.Hex(), ethAmount, gasEstimates) -} - -// SetFulfillmentPermission sets fulfillment permission for particular address -func (e *LegacyEthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.oracle.SetFulfillmentPermission(opts, common.HexToAddress(address), allowed) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) -} - -// LegacyEthereumAPIConsumer API consumer for job type "directrequest" tests -type LegacyEthereumAPIConsumer struct { - address *common.Address - client blockchain.EVMClient - consumer *test_api_consumer_wrapper.TestAPIConsumer -} - -func (e *LegacyEthereumAPIConsumer) Address() string { - return e.address.Hex() -} - -func (e *LegacyEthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - return e.consumer.CurrentRoundID(opts) -} - -func (e *LegacyEthereumAPIConsumer) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ - To: e.address, - }) - if err != nil { - return err - } - return e.client.Fund(e.address.Hex(), ethAmount, gasEstimates) -} - -func (e *LegacyEthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - data, err := e.consumer.Data(opts) - if err != nil { - return nil, err - } - return data, nil -} - -// CreateRequestTo creates request to an oracle for particular jobID with params -func (e *LegacyEthereumAPIConsumer) CreateRequestTo( - oracleAddr string, - jobID [32]byte, - payment *big.Int, - url string, - path string, - times *big.Int, -) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.consumer.CreateRequestTo(opts, common.HexToAddress(oracleAddr), jobID, payment, url, path, times) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) -} - -// EthereumStaking -type EthereumStaking struct { - client blockchain.EVMClient - staking *eth_contracts.Staking - address *common.Address -} - -func (f *EthereumStaking) Address() string { - return f.address.Hex() -} - -// Fund sends specified currencies to the contract -func (f *EthereumStaking) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ - To: f.address, - }) - if err != nil { - return err - } - return f.client.Fund(f.address.Hex(), ethAmount, gasEstimates) -} - -func (f *EthereumStaking) AddOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.AddOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) RemoveOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.RemoveOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) SetFeedOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.SetFeedOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) RaiseAlert() error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.RaiseAlert(opts) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) Start(amount *big.Int, initialRewardRate *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.Start(opts, amount, initialRewardRate) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) SetMerkleRoot(newMerkleRoot [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.SetMerkleRoot(opts, newMerkleRoot) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// EthereumFunctionsOracleEventsMock represents the basic events mock contract -type EthereumFunctionsOracleEventsMock struct { - client blockchain.EVMClient - eventsMock *functions_oracle_events_mock.FunctionsOracleEventsMock - address *common.Address -} - -func (f *EthereumFunctionsOracleEventsMock) Address() string { - return f.address.Hex() +// OCRv2Config represents the config for the OCRv2 contract +type OCRv2Config struct { + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + TypedOnchainConfig21 i_keeper_registry_master_wrapper_2_1.IAutomationV21PlusCommonOnchainConfigLegacy + TypedOnchainConfig22 i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig + OffchainConfigVersion uint64 + OffchainConfig []byte } -func (f *EthereumFunctionsOracleEventsMock) OracleResponse(requestId [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOracleResponse(opts, requestId) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +type EthereumFunctionsLoadStats struct { + LastRequestID string + LastResponse string + LastError string + Total uint32 + Succeeded uint32 + Errored uint32 + Empty uint32 } -func (f *EthereumFunctionsOracleEventsMock) OracleRequest(requestId [32]byte, requestingContract common.Address, requestInitiator common.Address, subscriptionId uint64, subscriptionOwner common.Address, data []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOracleRequest(opts, requestId, requestingContract, requestInitiator, subscriptionId, subscriptionOwner, data) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func Bytes32ToSlice(a [32]byte) (r []byte) { + r = append(r, a[:]...) + return } -func (f *EthereumFunctionsOracleEventsMock) UserCallbackError(requestId [32]byte, reason string) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitUserCallbackError(opts, requestId, reason) - if err != nil { - return err +// DefaultOffChainAggregatorOptions returns some base defaults for deploying an OCR contract +func DefaultOffChainAggregatorOptions() OffchainOptions { + return OffchainOptions{ + MaximumGasPrice: uint32(3000), + ReasonableGasPrice: uint32(10), + MicroLinkPerEth: uint32(500), + LinkGweiPerObservation: uint32(500), + LinkGweiPerTransmission: uint32(500), + MinimumAnswer: big.NewInt(1), + MaximumAnswer: big.NewInt(50000000000000000), + Decimals: 8, + Description: "Test OCR", + } +} + +// DefaultOffChainAggregatorConfig returns some base defaults for configuring an OCR contract +func DefaultOffChainAggregatorConfig(numberNodes int) OffChainAggregatorConfig { + if numberNodes <= 4 { + log.Err(fmt.Errorf("insufficient number of nodes (%d) supplied for OCR, need at least 5", numberNodes)). + Int("Number Chainlink Nodes", numberNodes). + Msg("You likely need more chainlink nodes to properly configure OCR, try 5 or more.") + } + s := []int{1} + // First node's stage already inputted as a 1 in line above, so numberNodes-1. + for i := 0; i < numberNodes-1; i++ { + s = append(s, 2) + } + return OffChainAggregatorConfig{ + AlphaPPB: 1, + DeltaC: time.Minute * 60, + DeltaGrace: time.Second * 12, + DeltaProgress: time.Second * 35, + DeltaStage: time.Second * 60, + DeltaResend: time.Second * 17, + DeltaRound: time.Second * 30, + RMax: 6, + S: s, + N: numberNodes, + F: 1, + OracleIdentities: []ocrConfigHelper.OracleIdentityExtra{}, } - return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsOracleEventsMock) UserCallbackRawError(requestId [32]byte, lowLevelData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitUserCallbackRawError(opts, requestId, lowLevelData) - if err != nil { - return err +func ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkK8sClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - return f.client.ProcessTransaction(tx) -} -// EthereumFunctionsBillingRegistryEventsMock represents the basic events mock contract -type EthereumFunctionsBillingRegistryEventsMock struct { - client blockchain.EVMClient - eventsMock *functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMock - address *common.Address -} - -func (f *EthereumFunctionsBillingRegistryEventsMock) Address() string { - return f.address.Hex() + return nodesAsInterface } -func (f *EthereumFunctionsBillingRegistryEventsMock) SubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionFunded(opts, subscriptionId, oldBalance, newBalance) - if err != nil { - return err +func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - return f.client.ProcessTransaction(tx) -} -func (f *EthereumFunctionsBillingRegistryEventsMock) BillingStart(requestId [32]byte, commitment functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMockCommitment) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitBillingStart(opts, requestId, commitment) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return nodesAsInterface } -func (f *EthereumFunctionsBillingRegistryEventsMock) BillingEnd(requestId [32]byte, subscriptionId uint64, signerPayment *big.Int, transmitterPayment *big.Int, totalCost *big.Int, success bool) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitBillingEnd(opts, requestId, subscriptionId, signerPayment, transmitterPayment, totalCost, success) - if err != nil { - return err +func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { + var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) + for i, contract := range contracts { + contractsAsInterface[i] = contract } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumStakingEventsMock represents the basic events mock contract -type LegacyEthereumStakingEventsMock struct { - client blockchain.EVMClient - eventsMock *eth_contracts.StakingEventsMock - address *common.Address -} - -func (f *LegacyEthereumStakingEventsMock) Address() string { - return f.address.Hex() -} -func (f *LegacyEthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitMaxCommunityStakeAmountIncreased(opts, maxStakeAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return contractsAsInterface } -func (f *LegacyEthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitPoolSizeIncreased(opts, maxPoolSize) - if err != nil { - return err +func V1OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregator) []OffChainAggregatorWithRounds { + var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) + for i, contract := range contracts { + contractsAsInterface[i] = contract } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitMaxOperatorStakeAmountIncreased(opts, maxStakeAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return contractsAsInterface } -func (f *LegacyEthereumStakingEventsMock) RewardInitialized(rate *big.Int, available *big.Int, startTimestamp *big.Int, endTimestamp *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRewardInitialized(opts, rate, available, startTimestamp, endTimestamp) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId *big.Int, rewardAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitAlertRaised(opts, alerter, roundId, rewardAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumStakingEventsMock) Staked(staker common.Address, newStake *big.Int, totalStake *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitStaked(opts, staker, newStake, totalStake) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumStakingEventsMock) OperatorAdded(operator common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOperatorAdded(opts, operator) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumStakingEventsMock) OperatorRemoved(operator common.Address, amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOperatorRemoved(opts, operator, amount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumStakingEventsMock) FeedOperatorsSet(feedOperators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitFeedOperatorsSet(opts, feedOperators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// EthereumOffchainAggregatorEventsMock represents the basic events mock contract -type EthereumOffchainAggregatorEventsMock struct { - client blockchain.EVMClient - eventsMock *eth_contracts.OffchainAggregatorEventsMock - address *common.Address -} - -func (f *EthereumOffchainAggregatorEventsMock) Address() string { - return f.address.Hex() -} - -func (f *EthereumOffchainAggregatorEventsMock) ConfigSet(previousConfigBlockNumber uint32, configCount uint64, signers []common.Address, transmitters []common.Address, threshold uint8, encodedConfigVersion uint64, encoded []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitConfigSet(opts, previousConfigBlockNumber, configCount, signers, transmitters, threshold, encodedConfigVersion, encoded) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumOffchainAggregatorEventsMock) NewTransmission(aggregatorRoundId uint32, answer *big.Int, transmitter common.Address, observations []*big.Int, observers []byte, rawReportContext [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitNewTransmission(opts, aggregatorRoundId, answer, transmitter, observations, observers, rawReportContext) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumKeeperRegistry11Mock represents the basic keeper registry 1.1 mock contract -type LegacyEthereumKeeperRegistry11Mock struct { - client blockchain.EVMClient - registryMock *keeper_registry_wrapper1_1_mock.KeeperRegistryMock - address *common.Address -} - -func (f *LegacyEthereumKeeperRegistry11Mock) Address() string { - return f.address.Hex() -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success bool, from common.Address, payment *big.Int, performData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepPerformed(opts, id, success, from, payment, performData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHeight uint64) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepCanceled(opts, id, atBlockHeight) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *big.Int, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitFundsWithdrawn(opts, id, amount, to) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Address, payees []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitKeepersUpdated(opts, keepers, payees) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, executeGas uint32, admin common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepRegistered(opts, id, executeGas, admin) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.Address, amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitFundsAdded(opts, id, from, amount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeepCount(_upkeepCount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetUpkeepCount(opts, _upkeepCount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetCanceledUpkeepList(_canceledUpkeepList []*big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetCanceledUpkeepList(opts, _canceledUpkeepList) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetKeeperList(_keepers []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetKeeperList(opts, _keepers) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetConfig(_paymentPremiumPPB uint32, _flatFeeMicroLink uint32, _blockCountPerTurn *big.Int, _checkGasLimit uint32, _stalenessSeconds *big.Int, _gasCeilingMultiplier uint16, _fallbackGasPrice *big.Int, _fallbackLinkPrice *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetConfig(opts, _paymentPremiumPPB, _flatFeeMicroLink, _blockCountPerTurn, _checkGasLimit, _stalenessSeconds, _gasCeilingMultiplier, _fallbackGasPrice, _fallbackLinkPrice) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, _target common.Address, _executeGas uint32, _balance *big.Int, _admin common.Address, _maxValidBlocknumber uint64, _lastKeeper common.Address, _checkData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetUpkeep(opts, id, _target, _executeGas, _balance, _admin, _maxValidBlocknumber, _lastKeeper, _checkData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetMinBalance(opts, id, minBalance) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performData []byte, maxLinkPayment *big.Int, gasLimit *big.Int, adjustedGasWei *big.Int, linkEth *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetCheckUpkeepData(opts, id, performData, maxLinkPayment, gasLimit, adjustedGasWei, linkEth) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, success bool) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetPerformUpkeepSuccess(opts, id, success) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumKeeperRegistrar12Mock represents the basic keeper registrar 1.2 mock contract -type LegacyEthereumKeeperRegistrar12Mock struct { - client blockchain.EVMClient - registrarMock *keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock - address *common.Address -} - -func (f *LegacyEthereumKeeperRegistrar12Mock) Address() string { - return f.address.Hex() -} - -func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, name string, encryptedEmail []byte, upkeepContract common.Address, gasLimit uint32, adminAddress common.Address, checkData []byte, amount *big.Int, source uint8) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registrarMock.EmitRegistrationRequested(opts, hash, name, encryptedEmail, upkeepContract, gasLimit, adminAddress, checkData, amount, source) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, displayName string, upkeepId *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registrarMock.EmitRegistrationApproved(opts, hash, displayName, upkeepId) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumKeeperRegistrar12Mock) SetRegistrationConfig(_autoApproveConfigType uint8, _autoApproveMaxAllowed uint32, _approvedCount uint32, _keeperRegistry common.Address, _minLINKJuels *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registrarMock.SetRegistrationConfig(opts, _autoApproveConfigType, _autoApproveMaxAllowed, _approvedCount, _keeperRegistry, _minLINKJuels) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumKeeperGasWrapperMock represents the basic keeper gas wrapper mock contract -type LegacyEthereumKeeperGasWrapperMock struct { - client blockchain.EVMClient - gasWrapperMock *gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock - address *common.Address -} - -func (f *LegacyEthereumKeeperGasWrapperMock) Address() string { - return f.address.Hex() -} - -func (f *LegacyEthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, payload []byte, gas *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.gasWrapperMock.SetMeasureCheckGasResult(opts, result, payload, gas) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract -type LegacyEthereumFunctionsV1EventsMock struct { - client blockchain.EVMClient - eventsMock *functions_v1_events_mock.FunctionsV1EventsMock - address *common.Address -} - -func (f *LegacyEthereumFunctionsV1EventsMock) Address() string { - return f.address.Hex() -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, subscriptionId uint64, totalCostJuels *big.Int, transmitter common.Address, resultCode uint8, response []byte, errByte []byte, callbackReturnData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestProcessed(opts, requestId, subscriptionId, totalCostJuels, transmitter, resultCode, response, errByte, callbackReturnData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, donId [32]byte, subscriptionId uint64, subscriptionOwner common.Address, requestingContract common.Address, requestInitiator common.Address, data []byte, dataVersion uint16, callbackGasLimit uint32, estimatedTotalCostJuels *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestStart(opts, requestId, donId, subscriptionId, subscriptionOwner, requestingContract, requestInitiator, data, dataVersion, callbackGasLimit, estimatedTotalCostJuels) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId uint64, fundsRecipient common.Address, fundsAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionCanceled(opts, subscriptionId, fundsRecipient, fundsAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscriptionId uint64, consumer common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionConsumerAdded(opts, subscriptionId, consumer) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscriptionId uint64, consumer common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionConsumerRemoved(opts, subscriptionId, consumer) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionCreated(opts, subscriptionId, owner) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionFunded(opts, subscriptionId, oldBalance, newBalance) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscriptionId uint64, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionOwnerTransferred(opts, subscriptionId, from, to) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(subscriptionId uint64, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionOwnerTransferRequested(opts, subscriptionId, from, to) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]byte, coordinator common.Address, transmitter common.Address, resultCode uint8) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestNotProcessed(opts, requestId, coordinator, transmitter, resultCode) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitContractUpdated(opts, id, from, to) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// LegacyEthereumFluxAggregator represents the basic flux aggregation contract -type LegacyEthereumFluxAggregator struct { - client blockchain.EVMClient - fluxAggregator *flux_aggregator_wrapper.FluxAggregator - address *common.Address -} - -func (f *LegacyEthereumFluxAggregator) Address() string { - return f.address.Hex() -} - -// Fund sends specified currencies to the contract -func (f *LegacyEthereumFluxAggregator) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ - To: f.address, - }) - if err != nil { - return err - } - return f.client.Fund(f.address.Hex(), ethAmount, gasEstimates) -} - -func (f *LegacyEthereumFluxAggregator) UpdateAvailableFunds() error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.UpdateAvailableFunds(opts) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - payment, err := f.fluxAggregator.PaymentAmount(opts) - if err != nil { - return nil, err - } - return payment, nil -} - -func (f *LegacyEthereumFluxAggregator) RequestNewRound(_ context.Context) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.RequestNewRound(opts) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// WatchSubmissionReceived subscribes to any submissions on a flux feed -func (f *LegacyEthereumFluxAggregator) WatchSubmissionReceived(ctx context.Context, eventChan chan<- *SubmissionEvent) error { - ethEventChan := make(chan *flux_aggregator_wrapper.FluxAggregatorSubmissionReceived) - sub, err := f.fluxAggregator.WatchSubmissionReceived(&bind.WatchOpts{}, ethEventChan, nil, nil, nil) - if err != nil { - return err - } - defer sub.Unsubscribe() - - for { - select { - case event := <-ethEventChan: - eventChan <- &SubmissionEvent{ - Contract: event.Raw.Address, - Submission: event.Submission, - Round: event.Round, - BlockNumber: event.Raw.BlockNumber, - Oracle: event.Oracle, - } - case err := <-sub.Err(): - return err - case <-ctx.Done(): - return nil - } - } -} - -func (f *LegacyEthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.SetRequesterPermissions(opts, addr, authorized, roundsDelay) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - addresses, err := f.fluxAggregator.GetOracles(opts) - if err != nil { - return nil, err - } - var oracleAddrs []string - for _, o := range addresses { - oracleAddrs = append(oracleAddrs, o.Hex()) - } - return oracleAddrs, nil -} - -func (f *LegacyEthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - rID, err := f.fluxAggregator.LatestRound(opts) - if err != nil { - return nil, err - } - return rID, nil -} - -func (f *LegacyEthereumFluxAggregator) WithdrawPayment( - _ context.Context, - from common.Address, - to common.Address, - amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.WithdrawPayment(opts, from, to, amount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *LegacyEthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - balance, err := f.fluxAggregator.WithdrawablePayment(opts, addr) - if err != nil { - return nil, err - } - return balance, nil -} - -func (f *LegacyEthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return flux_aggregator_wrapper.LatestRoundData{}, err - } - return lr, nil -} - -// GetContractData retrieves basic data for the flux aggregator contract -func (f *LegacyEthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - - allocated, err := f.fluxAggregator.AllocatedFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - available, err := f.fluxAggregator.AvailableFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - latestRound := RoundData(lr) - - oracles, err := f.fluxAggregator.GetOracles(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - return &FluxAggregatorData{ - AllocatedFunds: allocated, - AvailableFunds: available, - LatestRoundData: latestRound, - Oracles: oracles, - }, nil -} - -// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins -func (f *LegacyEthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := f.fluxAggregator.ChangeOracles(opts, o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// Description returns the description of the flux aggregator contract -func (f *LegacyEthereumFluxAggregator) Description(ctxt context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctxt, - } - return f.fluxAggregator.Description(opts) -} - -// FluxAggregatorRoundConfirmer is a header subscription that awaits for a certain flux round to be completed -type FluxAggregatorRoundConfirmer struct { - fluxInstance FluxAggregator - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - complete bool - l zerolog.Logger -} - -// NewFluxAggregatorRoundConfirmer provides a new instance of a FluxAggregatorRoundConfirmer -func NewFluxAggregatorRoundConfirmer( - contract FluxAggregator, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *FluxAggregatorRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &FluxAggregatorRoundConfirmer{ - fluxInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, - } -} - -// ReceiveHeader will query the latest FluxAggregator round and check to see whether the round has confirmed -func (f *FluxAggregatorRoundConfirmer) ReceiveHeader(header blockchain.NodeHeader) error { - if f.complete { - return nil - } - lr, err := f.fluxInstance.LatestRoundID(context.Background()) - if err != nil { - return err - } - logFields := map[string]any{ - "Contract Address": f.fluxInstance.Address(), - "Current Round": lr.Int64(), - "Waiting for Round": f.roundID.Int64(), - "Header Number": header.Number.Uint64(), - } - if lr.Cmp(f.roundID) >= 0 { - f.l.Info().Fields(logFields).Msg("FluxAggregator round completed") - f.complete = true - f.doneChan <- struct{}{} - } else { - f.l.Debug().Fields(logFields).Msg("Waiting for FluxAggregator round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (f *FluxAggregatorRoundConfirmer) Wait() error { - defer func() { f.complete = true }() - for { - select { - case <-f.doneChan: - f.cancel() - return nil - case <-f.context.Done(): - return fmt.Errorf("timeout waiting for flux round to confirm: %d", f.roundID) - } - } -} - -func (f *FluxAggregatorRoundConfirmer) Complete() bool { - return f.complete -} - -// LegacyEthereumLinkToken represents a LinkToken address -type LegacyEthereumLinkToken struct { - client blockchain.EVMClient - instance *link_token_interface.LinkToken - address common.Address - l zerolog.Logger -} - -// Fund the LINK Token contract with ETH to distribute the token -func (l *LegacyEthereumLinkToken) Fund(ethAmount *big.Float) error { - gasEstimates, err := l.client.EstimateGas(ethereum.CallMsg{ - To: &l.address, - }) - if err != nil { - return err - } - return l.client.Fund(l.address.Hex(), ethAmount, gasEstimates) -} - -func (l *LegacyEthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().Address()), - Context: ctx, - } - balance, err := l.instance.BalanceOf(opts, common.HexToAddress(addr)) - if err != nil { - return nil, err +func GetRegistryContractABI(version contractsethereum.KeeperRegistryVersion) (*abi.ABI, error) { + var ( + contractABI *abi.ABI + err error + ) + switch version { + case contractsethereum.RegistryVersion_1_0, contractsethereum.RegistryVersion_1_1: + contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_1_2: + contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_1_3: + contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_0: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_1: + contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_2: + contractABI, err = iregistry22.IAutomationRegistryMasterMetaData.GetAbi() + default: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() } - return balance, nil + + return contractABI, err } -// Name returns the name of the link token -func (l *LegacyEthereumLinkToken) Name(ctxt context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().Address()), - Context: ctxt, +// DefaultFluxAggregatorOptions produces some basic defaults for a flux aggregator contract +func DefaultFluxAggregatorOptions() FluxAggregatorOptions { + return FluxAggregatorOptions{ + PaymentAmount: big.NewInt(1), + Timeout: uint32(30), + MinSubValue: big.NewInt(0), + MaxSubValue: big.NewInt(1000000000000), + Decimals: uint8(0), + Description: "Test Flux Aggregator", } - return l.instance.Name(opts) } -func (l *LegacyEthereumLinkToken) Address() string { - return l.address.Hex() +// EthereumOffchainAggregator represents the offchain aggregation contract +type EthereumOffchainAggregator struct { + client *seth.Client + ocr *offchainaggregator.OffchainAggregator + address *common.Address + l zerolog.Logger } -func (l *LegacyEthereumLinkToken) Approve(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) +func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { + abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("Approving LINK Transfer") - tx, err := l.instance.Approve(opts, common.HexToAddress(to), amount) + seth.ContractStore.AddABI("OffChainAggregator", *abi) + seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) + + ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return l.client.ProcessTransaction(tx) + + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &contractAddress, + l: l, + }, nil } -func (l *LegacyEthereumLinkToken) Transfer(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return err - } - l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("Transferring LINK") - tx, err := l.instance.Transfer(opts, common.HexToAddress(to), amount) +func DeployOffchainAggregator(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregator, error) { + abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return l.client.ProcessTransaction(tx) -} -func (l *LegacyEthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) + ocrDeploymentData, err := seth.DeployContract( + seth.NewTXOpts(), + "OffChainAggregator", + *abi, + common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin), + offchainOptions.MaximumGasPrice, + offchainOptions.ReasonableGasPrice, + offchainOptions.MicroLinkPerEth, + offchainOptions.LinkGweiPerObservation, + offchainOptions.LinkGweiPerTransmission, + linkTokenAddress, + offchainOptions.MinimumAnswer, + offchainOptions.MaximumAnswer, + offchainOptions.BillingAccessController, + offchainOptions.RequesterAccessController, + offchainOptions.Decimals, + offchainOptions.Description) if err != nil { - return nil, err + return EthereumOffchainAggregator{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - tx, err := l.instance.TransferAndCall(opts, common.HexToAddress(to), amount, data) + + ocr, err := offchainaggregator.NewOffchainAggregator(ocrDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return nil, err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Str("TxHash", tx.Hash().String()). - Msg("Transferring and Calling LINK") - return tx, l.client.ProcessTransaction(tx) -} - -func (l *LegacyEthereumLinkToken) TransferAndCallFromKey(_ string, _ *big.Int, _ []byte, _ int) (*types.Transaction, error) { - panic("supported only with Seth") -} -// LegacyEthereumOffchainAggregator represents the offchain aggregation contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOffchainAggregator instead -type LegacyEthereumOffchainAggregator struct { - client blockchain.EVMClient - ocr *offchainaggregator.OffchainAggregator - address *common.Address - l zerolog.Logger + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &ocrDeploymentData.Address, + l: l, + }, nil } // SetPayees sets wallets for the contract to pay out to? -func (o *LegacyEthereumOffchainAggregator) SetPayees( +func (o *EthereumOffchainAggregator) SetPayees( transmitters, payees []string, ) error { - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) - if err != nil { - return err - } var transmittersAddr, payeesAddr []common.Address for _, tr := range transmitters { transmittersAddr = append(transmittersAddr, common.HexToAddress(tr)) @@ -1333,15 +278,12 @@ func (o *LegacyEthereumOffchainAggregator) SetPayees( Str("OCR Address", o.Address()). Msg("Setting OCR Payees") - tx, err := o.ocr.SetPayees(opts, transmittersAddr, payeesAddr) - if err != nil { - return err - } - return o.client.ProcessTransaction(tx) + _, err := o.client.Decode(o.ocr.SetPayees(o.client.NewTXOpts(), transmittersAddr, payeesAddr)) + return err } // SetConfig sets the payees and the offchain reporting protocol configuration -func (o *LegacyEthereumOffchainAggregator) SetConfig( +func (o *EthereumOffchainAggregator) SetConfig( chainlinkNodes []ChainlinkNodeWithKeysAndAddress, ocrConfig OffChainAggregatorConfig, transmitters []common.Address, @@ -1410,54 +352,39 @@ func (o *LegacyEthereumOffchainAggregator) SetConfig( return err } - // Set Config - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := o.ocr.SetConfig(opts, signers, transmitters, threshold, encodedConfigVersion, encodedConfig) - if err != nil { - return err - } - return o.client.ProcessTransaction(tx) + // fails with error setting OCR config for contract '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82': both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified + // but we only have gasPrice set... It also fails with the same error when we enable EIP-1559 + // fails when we wait for it to be minted, inside the wrapper there's no error when we call it, so it must be something inside smart contract + // that's reverting it and maybe the error message is completely off + _, err = o.client.Decode(o.ocr.SetConfig(o.client.NewTXOpts(), signers, transmitters, threshold, encodedConfigVersion, encodedConfig)) + return err } // RequestNewRound requests the OCR contract to create a new round -func (o *LegacyEthereumOffchainAggregator) RequestNewRound() error { - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := o.ocr.RequestNewRound(opts) - if err != nil { - return err - } +func (o *EthereumOffchainAggregator) RequestNewRound() error { o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") - - return o.client.ProcessTransaction(tx) + _, err := o.client.Decode(o.ocr.RequestNewRound(o.client.NewTXOpts())) + return err } // GetLatestAnswer returns the latest answer from the OCR contract -func (o *LegacyEthereumOffchainAggregator) GetLatestAnswer(ctxt context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: ctxt, - } - return o.ocr.LatestAnswer(opts) +func (o *EthereumOffchainAggregator) GetLatestAnswer(ctx context.Context) (*big.Int, error) { + return o.ocr.LatestAnswer(&bind.CallOpts{ + From: o.client.Addresses[0], + Context: ctx, + }) } -func (o *LegacyEthereumOffchainAggregator) Address() string { +func (o *EthereumOffchainAggregator) Address() string { return o.address.Hex() } // GetLatestRound returns data from the latest round -func (o *LegacyEthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), +func (o *EthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { + roundData, err := o.ocr.LatestRoundData(&bind.CallOpts{ + From: o.client.Addresses[0], Context: ctx, - } - - roundData, err := o.ocr.LatestRoundData(opts) + }) if err != nil { return nil, err } @@ -1471,11 +398,8 @@ func (o *LegacyEthereumOffchainAggregator) GetLatestRound(ctx context.Context) ( }, err } -func (o *LegacyEthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := o.ocr.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) +func (o *EthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := o.ocr.LatestRoundData(o.client.NewCallOpts()) if err != nil { return nil, err } @@ -1483,12 +407,11 @@ func (o *LegacyEthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, } // GetRound retrieves an OCR round by the round ID -func (o *LegacyEthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), +func (o *EthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { + roundData, err := o.ocr.GetRoundData(&bind.CallOpts{ + From: o.client.Addresses[0], Context: ctx, - } - roundData, err := o.ocr.GetRoundData(opts, roundID) + }, roundID) if err != nil { return nil, err } @@ -1503,1046 +426,1060 @@ func (o *LegacyEthereumOffchainAggregator) GetRound(ctx context.Context, roundID } // ParseEventAnswerUpdated parses the log for event AnswerUpdated -func (o *LegacyEthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { +func (o *EthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { return o.ocr.ParseAnswerUpdated(eventLog) } -// RunlogRoundConfirmer is a header subscription that awaits for a certain Runlog round to be completed -type RunlogRoundConfirmer struct { - consumer APIConsumer - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - l zerolog.Logger +// LegacyEthereumOperatorFactory represents operator factory contract +type EthereumOperatorFactory struct { + address *common.Address + client *seth.Client + operatorFactory *operator_factory.OperatorFactory } -// NewRunlogRoundConfirmer provides a new instance of a RunlogRoundConfirmer -func NewRunlogRoundConfirmer( - contract APIConsumer, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *RunlogRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &RunlogRoundConfirmer{ - consumer: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, +func DeployEthereumOperatorFactory(seth *seth.Client, linkTokenAddress common.Address) (EthereumOperatorFactory, error) { + abi, err := operator_factory.OperatorFactoryMetaData.GetAbi() + if err != nil { + return EthereumOperatorFactory{}, fmt.Errorf("failed to get OperatorFactory ABI: %w", err) + } + operatorData, err := seth.DeployContract(seth.NewTXOpts(), "OperatorFactory", *abi, common.FromHex(operator_factory.OperatorFactoryMetaData.Bin), linkTokenAddress) + if err != nil { + return EthereumOperatorFactory{}, fmt.Errorf("OperatorFactory instance deployment have failed: %w", err) + } + + operatorFactory, err := operator_factory.NewOperatorFactory(operatorData.Address, seth.Client) + if err != nil { + return EthereumOperatorFactory{}, fmt.Errorf("failed to instantiate OperatorFactory instance: %w", err) } + + return EthereumOperatorFactory{ + address: &operatorData.Address, + client: seth, + operatorFactory: operatorFactory, + }, nil +} + +func (e *EthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { + return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) +} + +func (e *EthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { + return e.operatorFactory.ParseOperatorCreated(eventLog) } -// ReceiveHeader will query the latest Runlog round and check to see whether the round has confirmed -func (o *RunlogRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - currentRoundID, err := o.consumer.RoundID(context.Background()) +func (e *EthereumOperatorFactory) Address() string { + return e.address.Hex() +} + +func (e *EthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return e.operatorFactory.DeployNewOperatorAndForwarder(e.client.NewTXOpts()) +} + +// EthereumOperator represents operator contract +type EthereumOperator struct { + address *common.Address + client *seth.Client + operator *operator_wrapper.Operator + l zerolog.Logger +} + +func LoadEthereumOperator(logger zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOperator, error) { + + abi, err := operator_wrapper.OperatorMetaData.GetAbi() if err != nil { - return err + return EthereumOperator{}, err } - logFields := map[string]any{ - "Contract Address": o.consumer.Address(), - "Current Round": currentRoundID.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currentRoundID.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("Runlog round completed") - o.doneChan <- struct{}{} - } else { - o.l.Debug().Fields(logFields).Msg("Waiting for Runlog round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *RunlogRoundConfirmer) Wait() error { - for { - select { - case <-o.doneChan: - o.cancel() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + seth.ContractStore.AddABI("EthereumOperator", *abi) + seth.ContractStore.AddBIN("EthereumOperator", common.FromHex(operator_wrapper.OperatorMetaData.Bin)) + + operator, err := operator_wrapper.NewOperator(contractAddress, seth.Client) + if err != nil { + return EthereumOperator{}, err } + + return EthereumOperator{ + address: &contractAddress, + client: seth, + operator: operator, + l: logger, + }, nil } -// OffchainAggregatorRoundConfirmer is a header subscription that awaits for a certain OCR round to be completed -type OffchainAggregatorRoundConfirmer struct { - ocrInstance OffchainAggregator - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - blocksSinceAnswer uint - complete bool - l zerolog.Logger +func (e *EthereumOperator) Address() string { + return e.address.Hex() } -// NewOffchainAggregatorRoundConfirmer provides a new instance of a OffchainAggregatorRoundConfirmer -func NewOffchainAggregatorRoundConfirmer( - contract OffchainAggregator, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *OffchainAggregatorRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &OffchainAggregatorRoundConfirmer{ - ocrInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - complete: false, - l: logger, - } +func (e *EthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { + e.l.Info(). + Str("ForwardersAddresses", fmt.Sprint(forwarders)). + Str("EoaAddresses", fmt.Sprint(eoa)). + Msg("Accepting Authorized Receivers") + _, err := e.client.Decode(e.operator.AcceptAuthorizedReceivers(e.client.NewTXOpts(), forwarders, eoa)) + return err } -// ReceiveHeader will query the latest OffchainAggregator round and check to see whether the round has confirmed -func (o *OffchainAggregatorRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - if channelClosed(o.doneChan) { - return nil +// EthereumAuthorizedForwarder represents authorized forwarder contract +type EthereumAuthorizedForwarder struct { + address *common.Address + client *seth.Client + authorizedForwarder *authorized_forwarder.AuthorizedForwarder +} + +func LoadEthereumAuthorizedForwarder(seth *seth.Client, contractAddress common.Address) (EthereumAuthorizedForwarder, error) { + abi, err := authorized_forwarder.AuthorizedForwarderMetaData.GetAbi() + if err != nil { + return EthereumAuthorizedForwarder{}, err } + seth.ContractStore.AddABI("AuthorizedForwarder", *abi) + seth.ContractStore.AddBIN("AuthorizedForwarder", common.FromHex(authorized_forwarder.AuthorizedForwarderMetaData.Bin)) - lr, err := o.ocrInstance.GetLatestRound(context.Background()) + authorizedForwarder, err := authorized_forwarder.NewAuthorizedForwarder(contractAddress, seth.Client) if err != nil { - return err + return EthereumAuthorizedForwarder{}, fmt.Errorf("failed to instantiate AuthorizedForwarder instance: %w", err) } - o.blocksSinceAnswer++ - currRound := lr.RoundId - logFields := map[string]any{ - "Contract Address": o.ocrInstance.Address(), - "Current Round": currRound.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currRound.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("OCR round completed") - o.doneChan <- struct{}{} - o.complete = true - } else { - o.l.Debug().Fields(logFields).Msg("Waiting on OCR Round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *OffchainAggregatorRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - close(o.doneChan) - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + + return EthereumAuthorizedForwarder{ + address: &contractAddress, + client: seth, + authorizedForwarder: authorizedForwarder, + }, nil +} + +// Owner return authorized forwarder owner address +func (e *EthereumAuthorizedForwarder) Owner(_ context.Context) (string, error) { + owner, err := e.authorizedForwarder.Owner(e.client.NewCallOpts()) + + return owner.Hex(), err +} + +func (e *EthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { + opts := &bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + } + authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) + if err != nil { + return nil, err + } + var sendersAddrs []string + for _, o := range authorizedSenders { + sendersAddrs = append(sendersAddrs, o.Hex()) } + return sendersAddrs, nil } -func (o *OffchainAggregatorRoundConfirmer) Complete() bool { - return o.complete +func (e *EthereumAuthorizedForwarder) Address() string { + return e.address.Hex() } -// OffchainAggregatorRoundConfirmer is a header subscription that awaits for a certain OCR round to be completed -type OffchainAggregatorV2RoundConfirmer struct { - ocrInstance OffchainAggregatorV2 - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - blocksSinceAnswer uint - complete bool - l zerolog.Logger +type EthereumOffchainAggregatorV2 struct { + address *common.Address + client *seth.Client + contract *ocr2aggregator.OCR2Aggregator + l zerolog.Logger } -// NewOffchainAggregatorRoundConfirmer provides a new instance of a OffchainAggregatorRoundConfirmer -func NewOffchainAggregatorV2RoundConfirmer( - contract OffchainAggregatorV2, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *OffchainAggregatorV2RoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &OffchainAggregatorV2RoundConfirmer{ - ocrInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - complete: false, - l: logger, +func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() + if err != nil { + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) + } + seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) + + ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) + if err != nil { + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &contractAddress, + l: l, + }, nil } -// ReceiveHeader will query the latest OffchainAggregator round and check to see whether the round has confirmed -func (o *OffchainAggregatorV2RoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - if channelClosed(o.doneChan) { - return nil +func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() + if err != nil { + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } + seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) + + ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *oAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), + linkTokenAddress, + offchainOptions.MinimumAnswer, + offchainOptions.MaximumAnswer, + offchainOptions.BillingAccessController, + offchainOptions.RequesterAccessController, + offchainOptions.Decimals, + offchainOptions.Description, + ) - lr, err := o.ocrInstance.GetLatestRound(context.Background()) if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - o.blocksSinceAnswer++ - currRound := lr.RoundId - logFields := map[string]any{ - "Contract Address": o.ocrInstance.Address(), - "Current Round": currRound.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currRound.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("OCR round completed") - o.doneChan <- struct{}{} - o.complete = true - } else { - o.l.Debug().Fields(logFields).Msg("Waiting on OCR Round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *OffchainAggregatorV2RoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - close(o.doneChan) - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + + ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &ocrDeploymentData2.Address, + l: l, + }, nil } -func (o *OffchainAggregatorV2RoundConfirmer) Complete() bool { - return o.complete +func (e *EthereumOffchainAggregatorV2) Address() string { + return e.address.Hex() } -// LegacyEthereumMockETHLINKFeed represents mocked ETH/LINK feed contract -type LegacyEthereumMockETHLINKFeed struct { - client blockchain.EVMClient - feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator - address *common.Address +func (e *EthereumOffchainAggregatorV2) RequestNewRound() error { + _, err := e.client.Decode(e.contract.RequestNewRound(e.client.NewTXOpts())) + return err } -func (v *LegacyEthereumMockETHLINKFeed) Address() string { - return v.address.Hex() +func (e *EthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { + return e.contract.LatestAnswer(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + }) } -func (v *LegacyEthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: context.Background(), +func (e *EthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { + data, err := e.contract.LatestRoundData(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, }) if err != nil { return nil, err } - return data.Ans, nil + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, nil } -func (v *LegacyEthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) +func (e *EthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { + data, err := e.contract.GetRoundData(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + }, roundID) + if err != nil { + return nil, err + } + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, nil +} + +func (e *EthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { + e.l.Info(). + Str("Transmitters", fmt.Sprintf("%v", transmitters)). + Str("Payees", fmt.Sprintf("%v", payees)). + Str("OCRv2 Address", e.Address()). + Msg("Setting OCRv2 Payees") + + var addTransmitters, addrPayees []common.Address + for _, t := range transmitters { + addTransmitters = append(addTransmitters, common.HexToAddress(t)) + } + for _, p := range payees { + addrPayees = append(addrPayees, common.HexToAddress(p)) + } + + _, err := e.client.Decode(e.contract.SetPayees(e.client.NewTXOpts(), addTransmitters, addrPayees)) + return err +} + +func (e *EthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { + e.l.Info(). + Str("Address", e.Address()). + Interface("Signers", ocrConfig.Signers). + Interface("Transmitters", ocrConfig.Transmitters). + Uint8("F", ocrConfig.F). + Bytes("OnchainConfig", ocrConfig.OnchainConfig). + Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). + Bytes("OffchainConfig", ocrConfig.OffchainConfig). + Msg("Setting OCRv2 Config") + + _, err := e.client.Decode(e.contract.SetConfig( + e.client.NewTXOpts(), + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + )) + return err +} + +func (e *EthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { + return e.contract.ParseAnswerUpdated(log) +} + +// EthereumLinkToken represents a LinkToken address +type EthereumLinkToken struct { + client *seth.Client + instance *link_token_interface.LinkToken + address common.Address + l zerolog.Logger +} + +func DeployLinkTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumLinkToken, error) { + linkTokenAbi, err := link_token_interface.LinkTokenMetaData.GetAbi() + if err != nil { + return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) + } + linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) + if err != nil { + return &EthereumLinkToken{}, fmt.Errorf("LinkToken instance deployment have failed: %w", err) + } + + linkToken, err := link_token_interface.NewLinkToken(linkDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) + } + + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: linkDeploymentData.Address, + l: l, + }, nil +} + +func LoadLinkTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumLinkToken, error) { + abi, err := link_token_interface.LinkTokenMetaData.GetAbi() + if err != nil { + return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) + } + + client.ContractStore.AddABI("LinkToken", *abi) + client.ContractStore.AddBIN("LinkToken", common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) + + linkToken, err := link_token_interface.NewLinkToken(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) } - return data.UpdatedAt, nil -} -// LegacyEthereumMockGASFeed represents mocked Gas feed contract -type LegacyEthereumMockGASFeed struct { - client blockchain.EVMClient - feed *mock_gas_aggregator_wrapper.MockGASAggregator - address *common.Address + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: address, + l: l, + }, nil } -func (v *LegacyEthereumMockGASFeed) Address() string { - return v.address.Hex() +// Fund the LINK Token contract with ETH to distribute the token +func (l *EthereumLinkToken) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds instead") } -// EthereumFlags represents flags contract -type EthereumFlags struct { - client blockchain.EVMClient - flags *flags_wrapper.Flags - address *common.Address -} +func (l *EthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { + return l.instance.BalanceOf(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }, common.HexToAddress(addr)) -func (e *EthereumFlags) Address() string { - return e.address.Hex() } -// GetFlag returns boolean if a flag was set for particular address -func (e *EthereumFlags) GetFlag(ctx context.Context, addr string) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +// Name returns the name of the link token +func (l *EthereumLinkToken) Name(ctx context.Context) (string, error) { + return l.instance.Name(&bind.CallOpts{ + From: l.client.Addresses[0], Context: ctx, - } - flag, err := e.flags.GetFlag(opts, common.HexToAddress(addr)) - if err != nil { - return false, err - } - return flag, nil -} - -// LegacyEthereumOperatorFactory represents operator factory contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOperatorFactory instead -type LegacyEthereumOperatorFactory struct { - address *common.Address - client blockchain.EVMClient - operatorFactory *operator_factory.OperatorFactory + }) } -func (e *LegacyEthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { - return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) +func (l *EthereumLinkToken) Address() string { + return l.address.Hex() } -func (e *LegacyEthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { - return e.operatorFactory.ParseOperatorCreated(eventLog) +func (l *EthereumLinkToken) Approve(to string, amount *big.Int) error { + l.l.Info(). + Str("From", l.client.Addresses[0].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Approving LINK Transfer") + _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (e *LegacyEthereumOperatorFactory) Address() string { - return e.address.Hex() +func (l *EthereumLinkToken) Transfer(to string, amount *big.Int) error { + l.l.Info(). + Str("From", l.client.Addresses[0].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Transferring LINK") + _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (e *LegacyEthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func (l *EthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { + l.l.Info(). + Str("From", l.client.Addresses[0].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Transferring and Calling LINK") + decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXOpts(), common.HexToAddress(to), amount, data)) if err != nil { return nil, err } - tx, err := e.operatorFactory.DeployNewOperatorAndForwarder(opts) + return decodedTx.Transaction, nil +} + +func (l *EthereumLinkToken) TransferAndCallFromKey(to string, amount *big.Int, data []byte, keyNum int) (*types.Transaction, error) { + l.l.Info(). + Str("From", l.client.Addresses[keyNum].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Transferring and Calling LINK") + decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXKeyOpts(keyNum), common.HexToAddress(to), amount, data)) if err != nil { return nil, err } - return tx, nil + return decodedTx.Transaction, nil } -// LegacyEthereumOperator represents operator contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOperator instead -type LegacyEthereumOperator struct { - address common.Address - client blockchain.EVMClient - operator *operator_wrapper.Operator - l zerolog.Logger -} +// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain +func DeployFluxAggregatorContract( + seth *seth.Client, + linkAddr string, + fluxOptions FluxAggregatorOptions, +) (FluxAggregator, error) { + abi, err := flux_aggregator_wrapper.FluxAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumFluxAggregator{}, fmt.Errorf("failed to get FluxAggregator ABI: %w", err) + } + seth.ContractStore.AddABI("FluxAggregator", *abi) + seth.ContractStore.AddBIN("FluxAggregator", common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin)) -func (e *LegacyEthereumOperator) Address() string { - return e.address.Hex() -} + fluxDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "FluxAggregator", *abi, common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin), + common.HexToAddress(linkAddr), + fluxOptions.PaymentAmount, + fluxOptions.Timeout, + fluxOptions.Validator, + fluxOptions.MinSubValue, + fluxOptions.MaxSubValue, + fluxOptions.Decimals, + fluxOptions.Description, + ) -func (e *LegacyEthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { - return err + return &EthereumFluxAggregator{}, fmt.Errorf("FluxAggregator instance deployment have failed: %w", err) } - e.l.Info(). - Str("ForwardersAddresses", fmt.Sprint(forwarders)). - Str("EoaAddresses", fmt.Sprint(eoa)). - Msg("Accepting Authorized Receivers") - tx, err := e.operator.AcceptAuthorizedReceivers(opts, forwarders, eoa) + + flux, err := flux_aggregator_wrapper.NewFluxAggregator(fluxDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return &EthereumFluxAggregator{}, fmt.Errorf("failed to instantiate FluxAggregator instance: %w", err) } - return e.client.ProcessTransaction(tx) + + return &EthereumFluxAggregator{ + client: seth, + address: &fluxDeploymentData.Address, + fluxAggregator: flux, + }, nil } -// LegacyEthereumAuthorizedForwarder represents authorized forwarder contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumAuthorizedForwarder instead -type LegacyEthereumAuthorizedForwarder struct { - address common.Address - client blockchain.EVMClient - authorizedForwarder *authorized_forwarder.AuthorizedForwarder +// EthereumFluxAggregator represents the basic flux aggregation contract +type EthereumFluxAggregator struct { + client *seth.Client + fluxAggregator *flux_aggregator_wrapper.FluxAggregator + address *common.Address } -// Owner return authorized forwarder owner address -func (e *LegacyEthereumAuthorizedForwarder) Owner(ctx context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - owner, err := e.authorizedForwarder.Owner(opts) +func (f *EthereumFluxAggregator) Address() string { + return f.address.Hex() +} - return owner.Hex(), err +// Fund sends specified currencies to the contract +func (f *EthereumFluxAggregator) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -func (e *LegacyEthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) - if err != nil { - return nil, err - } - var sendersAddrs []string - for _, o := range authorizedSenders { - sendersAddrs = append(sendersAddrs, o.Hex()) - } - return sendersAddrs, nil +func (f *EthereumFluxAggregator) UpdateAvailableFunds() error { + _, err := f.client.Decode(f.fluxAggregator.UpdateAvailableFunds(f.client.NewTXOpts())) + return err } -func (e *LegacyEthereumAuthorizedForwarder) Address() string { - return e.address.Hex() +func (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.PaymentAmount(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -// EthereumMockAggregatorProxy represents mock aggregator proxy contract -type EthereumMockAggregatorProxy struct { - address *common.Address - client blockchain.EVMClient - mockAggregatorProxy *mock_aggregator_proxy.MockAggregatorProxy +func (f *EthereumFluxAggregator) RequestNewRound(context.Context) error { + _, err := f.client.Decode(f.fluxAggregator.RequestNewRound(f.client.NewTXOpts())) + return err } -func (e *EthereumMockAggregatorProxy) Address() string { - return e.address.Hex() +// WatchSubmissionReceived subscribes to any submissions on a flux feed +func (f *EthereumFluxAggregator) WatchSubmissionReceived(_ context.Context, _ chan<- *SubmissionEvent) error { + panic("do not use this method, instead use XXXX") } -func (e *EthereumMockAggregatorProxy) UpdateAggregator(aggregator common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.mockAggregatorProxy.UpdateAggregator(opts, aggregator) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (f *EthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { + _, err := f.client.Decode(f.fluxAggregator.SetRequesterPermissions(f.client.NewTXOpts(), addr, authorized, roundsDelay)) + return err } -func (e *EthereumMockAggregatorProxy) Aggregator() (common.Address, error) { - addr, err := e.mockAggregatorProxy.Aggregator(&bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), +func (f *EthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { + addresses, err := f.fluxAggregator.GetOracles(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, }) if err != nil { - return common.Address{}, err + return nil, err } - return addr, nil -} - -func channelClosed(ch <-chan struct{}) bool { - select { - case <-ch: - return true - default: + var oracleAddrs []string + for _, o := range addresses { + oracleAddrs = append(oracleAddrs, o.Hex()) } - - return false + return oracleAddrs, nil } -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOffchainAggregatorV2 instead -type LegacyEthereumOffchainAggregatorV2 struct { - address *common.Address - client blockchain.EVMClient - contract *ocr2aggregator.OCR2Aggregator - l zerolog.Logger +func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.LatestRound(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -// OCRv2Config represents the config for the OCRv2 contract -type OCRv2Config struct { - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - TypedOnchainConfig21 i_keeper_registry_master_wrapper_2_1.IAutomationV21PlusCommonOnchainConfigLegacy - TypedOnchainConfig22 i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig - OffchainConfigVersion uint64 - OffchainConfig []byte +func (f *EthereumFluxAggregator) WithdrawPayment( + _ context.Context, + from common.Address, + to common.Address, + amount *big.Int) error { + _, err := f.client.Decode(f.fluxAggregator.WithdrawPayment(f.client.NewTXOpts(), from, to, amount)) + return err } -func (e *LegacyEthereumOffchainAggregatorV2) Address() string { - return e.address.Hex() +func (f *EthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { + return f.fluxAggregator.WithdrawablePayment(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }, addr) } -func (e *LegacyEthereumOffchainAggregatorV2) RequestNewRound() error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.contract.RequestNewRound(opts) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (f *EthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { + return f.fluxAggregator.LatestRoundData(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { +// GetContractData retrieves basic data for the flux aggregator contract +func (f *EthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), + From: f.client.Addresses[0], Context: ctx, } - return e.contract.LatestAnswer(opts) -} -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, + allocated, err := f.fluxAggregator.AllocatedFunds(opts) + if err != nil { + return &FluxAggregatorData{}, err } - data, err := e.contract.LatestRoundData(opts) + + available, err := f.fluxAggregator.AvailableFunds(opts) if err != nil { - return nil, err + return &FluxAggregatorData{}, err } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} -func (e *LegacyEthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, + lr, err := f.fluxAggregator.LatestRoundData(opts) + if err != nil { + return &FluxAggregatorData{}, err } - data, err := e.contract.GetRoundData(opts, roundID) + latestRound := RoundData(lr) + + oracles, err := f.fluxAggregator.GetOracles(opts) if err != nil { - return nil, err + return &FluxAggregatorData{}, err } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, + + return &FluxAggregatorData{ + AllocatedFunds: allocated, + AvailableFunds: available, + LatestRoundData: latestRound, + Oracles: oracles, }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins +func (f *EthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { + _, err := f.client.Decode(f.fluxAggregator.ChangeOracles(f.client.NewTXOpts(), o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds)) if err != nil { return err } - e.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCRv2 Address", e.Address()). - Msg("Setting OCRv2 Payees") + return err +} - var addTransmitters, addrPayees []common.Address - for _, t := range transmitters { - addTransmitters = append(addTransmitters, common.HexToAddress(t)) - } - for _, p := range payees { - addrPayees = append(addrPayees, common.HexToAddress(p)) - } +// Description returns the description of the flux aggregator contract +func (f *EthereumFluxAggregator) Description(ctxt context.Context) (string, error) { + return f.fluxAggregator.Description(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctxt, + }) +} - tx, err := e.contract.SetPayees(opts, addTransmitters, addrPayees) +func DeployOracle(seth *seth.Client, linkAddr string) (Oracle, error) { + abi, err := oracle_wrapper.OracleMetaData.GetAbi() if err != nil { - return err + return &EthereumOracle{}, fmt.Errorf("failed to get Oracle ABI: %w", err) } - return e.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("Oracle", *abi) + seth.ContractStore.AddBIN("Oracle", common.FromHex(oracle_wrapper.OracleMetaData.Bin)) + + oracleDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "Oracle", *abi, common.FromHex(oracle_wrapper.OracleMetaData.Bin), + common.HexToAddress(linkAddr), + ) -func (e *LegacyEthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { - return err + return &EthereumOracle{}, fmt.Errorf("Oracle instance deployment have failed: %w", err) } - e.l.Info(). - Str("Address", e.Address()). - Interface("Signers", ocrConfig.Signers). - Interface("Transmitters", ocrConfig.Transmitters). - Uint8("F", ocrConfig.F). - Bytes("OnchainConfig", ocrConfig.OnchainConfig). - Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). - Bytes("OffchainConfig", ocrConfig.OffchainConfig). - Msg("Setting OCRv2 Config") - tx, err := e.contract.SetConfig( - opts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) + + oracle, err := oracle_wrapper.NewOracle(oracleDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return &EthereumOracle{}, fmt.Errorf("Oracle to instantiate FluxAggregator instance: %w", err) } - return e.client.ProcessTransaction(tx) -} -func (e *LegacyEthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { - return e.contract.ParseAnswerUpdated(log) + return &EthereumOracle{ + client: seth, + address: &oracleDeploymentData.Address, + oracle: oracle, + }, nil } -// EthereumKeeperRegistryCheckUpkeepGasUsageWrapper represents a gas wrapper for keeper registry -type EthereumKeeperRegistryCheckUpkeepGasUsageWrapper struct { - address *common.Address - client blockchain.EVMClient - gasUsageWrapper *gas_wrapper.KeeperRegistryCheckUpkeepGasUsageWrapper +// EthereumOracle oracle for "directrequest" job tests +type EthereumOracle struct { + address *common.Address + client *seth.Client + oracle *oracle_wrapper.Oracle } -func (e *EthereumKeeperRegistryCheckUpkeepGasUsageWrapper) Address() string { +func (e *EthereumOracle) Address() string { return e.address.Hex() } -/* Functions 1_0_0 */ - -type LegacyEthereumFunctionsRouter struct { - address common.Address - client blockchain.EVMClient - instance *functions_router.FunctionsRouter - l zerolog.Logger +func (e *EthereumOracle) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -func (e *LegacyEthereumFunctionsRouter) Address() string { - return e.address.Hex() +// SetFulfillmentPermission sets fulfillment permission for particular address +func (e *EthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { + _, err := e.client.Decode(e.oracle.SetFulfillmentPermission(e.client.NewTXOpts(), common.HexToAddress(address), allowed)) + return err } -func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return 0, err - } - tx, err := e.instance.CreateSubscriptionWithConsumer(opts, common.HexToAddress(consumer)) - if err != nil { - return 0, err - } - if err := e.client.ProcessTransaction(tx); err != nil { - return 0, err - } - r, err := e.client.GetTxReceipt(tx.Hash()) +func DeployAPIConsumer(seth *seth.Client, linkAddr string) (APIConsumer, error) { + abi, err := test_api_consumer_wrapper.TestAPIConsumerMetaData.GetAbi() if err != nil { - return 0, err - } - for _, l := range r.Logs { - e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() + return &EthereumAPIConsumer{}, fmt.Errorf("failed to get TestAPIConsumer ABI: %w", err) } - topicsMap := map[string]interface{}{} + seth.ContractStore.AddABI("TestAPIConsumer", *abi) + seth.ContractStore.AddBIN("TestAPIConsumer", common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin)) + + consumerDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "TestAPIConsumer", *abi, common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin), + common.HexToAddress(linkAddr), + ) - fabi, err := abi.JSON(strings.NewReader(functions_router.FunctionsRouterABI)) if err != nil { - return 0, err - } - for _, ev := range fabi.Events { - e.l.Info().Str("EventName", ev.Name).Send() - } - topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} - topicOneHash := []common.Hash{r.Logs[0].Topics[1:][0]} - if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { - return 0, fmt.Errorf("failed to decode topic value, err: %w", err) + return &EthereumAPIConsumer{}, fmt.Errorf("TestAPIConsumer instance deployment have failed: %w", err) } - e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send() - if topicsMap["subscriptionId"] == 0 { - return 0, fmt.Errorf("failed to decode subscription ID after creation") + + consumer, err := test_api_consumer_wrapper.NewTestAPIConsumer(consumerDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumAPIConsumer{}, fmt.Errorf("failed to instantiate TestAPIConsumer instance: %w", err) } - return topicsMap["subscriptionId"].(uint64), nil + + return &EthereumAPIConsumer{ + client: seth, + address: &consumerDeploymentData.Address, + consumer: consumer, + }, nil } -type LegacyEthereumFunctionsCoordinator struct { - address common.Address - client blockchain.EVMClient - instance *functions_coordinator.FunctionsCoordinator +// EthereumAPIConsumer API consumer for job type "directrequest" tests +type EthereumAPIConsumer struct { + address *common.Address + client *seth.Client + consumer *test_api_consumer_wrapper.TestAPIConsumer } -func (e *LegacyEthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), - } - return e.instance.GetThresholdPublicKey(opts) +func (e *EthereumAPIConsumer) Address() string { + return e.address.Hex() } -func (e *LegacyEthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), - } - return e.instance.GetDONPublicKey(opts) +func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { + return e.consumer.CurrentRoundID(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + }) } -func (e *LegacyEthereumFunctionsCoordinator) Address() string { - return e.address.Hex() +func (e *EthereumAPIConsumer) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -type LegacyEthereumFunctionsLoadTestClient struct { - address common.Address - client blockchain.EVMClient - instance *functions_load_test_client.FunctionsLoadTestClient +func (e *EthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { + return e.consumer.Data(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + }) } -func (e *LegacyEthereumFunctionsLoadTestClient) Address() string { - return e.address.Hex() +// CreateRequestTo creates request to an oracle for particular jobID with params +func (e *EthereumAPIConsumer) CreateRequestTo( + oracleAddr string, + jobID [32]byte, + payment *big.Int, + url string, + path string, + times *big.Int, +) error { + _, err := e.client.Decode(e.consumer.CreateRequestTo(e.client.NewTXOpts(), common.HexToAddress(oracleAddr), jobID, payment, url, path, times)) + return err } -type EthereumFunctionsLoadStats struct { - LastRequestID string - LastResponse string - LastError string - Total uint32 - Succeeded uint32 - Errored uint32 - Empty uint32 +// EthereumMockETHLINKFeed represents mocked ETH/LINK feed contract +type EthereumMockETHLINKFeed struct { + client *seth.Client + feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator + address *common.Address } -func Bytes32ToSlice(a [32]byte) (r []byte) { - r = append(r, a[:]...) - return +func (v *EthereumMockETHLINKFeed) Address() string { + return v.address.Hex() } -func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +func (v *EthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { + data, err := v.feed.LatestRoundData(&bind.CallOpts{ + From: v.client.Addresses[0], Context: context.Background(), - } - lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(opts) + }) if err != nil { return nil, err } - return &EthereumFunctionsLoadStats{ - LastRequestID: string(Bytes32ToSlice(lr)), - LastResponse: string(lbody), - LastError: string(lerr), - Total: total, - Succeeded: succeeded, - Errored: errored, - Empty: empty, - }, nil + return data.Ans, nil } -func (e *LegacyEthereumFunctionsLoadTestClient) ResetStats() error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.ResetStats(opts) +func (v *EthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := v.feed.LatestRoundData(&bind.CallOpts{ + From: v.client.Addresses[0], + Context: context.Background(), + }) if err != nil { - return err + return nil, err } - return e.client.ProcessTransaction(tx) + return data.UpdatedAt, nil } -func (e *LegacyEthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMockETHLINKFeed(client *seth.Client, answer *big.Int) (MockETHLINKFeed, error) { + abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) } - tx, err := e.instance.SendRequest(opts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) + data, err := client.DeployContract(client.NewTXOpts(), "MockETHLINKFeed", *abi, common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin), answer) if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("MockETHLINKFeed instance deployment have failed: %w", err) } - return e.client.ProcessTransaction(tx) -} -func (e *LegacyEthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.SendRequestWithDONHostedSecrets(opts, times, source, slotID, slotVersion, args, subscriptionId, donID) + instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) } - return e.client.ProcessTransaction(tx) -} -type EthereumMercuryVerifier struct { - address common.Address - client blockchain.EVMClient - instance *verifier.Verifier - l zerolog.Logger -} - -func (e *EthereumMercuryVerifier) Address() common.Address { - return e.address + return &EthereumMockETHLINKFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func (e *EthereumMercuryVerifier) Verify(signedReport []byte, sender common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.Verify(opts, signedReport, sender) +func LoadMockETHLINKFeed(client *seth.Client, address common.Address) (MockETHLINKFeed, error) { + abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) } - return e.client.ProcessTransaction(tx) -} + client.ContractStore.AddABI("MockETHLINKFeed", *abi) + client.ContractStore.AddBIN("MockETHLINKFeed", common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin)) -func (e *EthereumMercuryVerifier) SetConfig(feedId [32]byte, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []verifier.CommonAddressAndWeight) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetConfig(opts, feedId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Hex("feedId", feedId[:]).Msg("Called EthereumMercuryVerifier.SetConfig()") + instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) -} -func (e *EthereumMercuryVerifier) LatestConfigDetails(ctx context.Context, feedId [32]byte) (verifier.LatestConfigDetails, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - d, err := e.instance.LatestConfigDetails(opts, feedId) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Hex("feedId", feedId[:]). - Interface("details", d). - Msg("Called EthereumMercuryVerifier.LatestConfigDetails()") - if err != nil { - return verifier.LatestConfigDetails{}, err - } - return d, nil + return &EthereumMockETHLINKFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -type EthereumMercuryVerifierProxy struct { - address common.Address - client blockchain.EVMClient - instance *verifier_proxy.VerifierProxy - l zerolog.Logger +// EthereumMockGASFeed represents mocked Gas feed contract +type EthereumMockGASFeed struct { + client *seth.Client + feed *mock_gas_aggregator_wrapper.MockGASAggregator + address *common.Address } -func (e *EthereumMercuryVerifierProxy) Address() common.Address { - return e.address +func (v *EthereumMockGASFeed) Address() string { + return v.address.Hex() } -func (e *EthereumMercuryVerifierProxy) InitializeVerifier(verifierAddress common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMockGASFeed(client *seth.Client, answer *big.Int) (MockGasFeed, error) { + abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) } - tx, err := e.instance.InitializeVerifier(opts, verifierAddress) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Str("verifierAddress", verifierAddress.Hex()). - Msg("Called EthereumMercuryVerifierProxy.InitializeVerifier()") + data, err := client.DeployContract(client.NewTXOpts(), "MockGasFeed", *abi, common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin), answer) if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("MockGasFeed instance deployment have failed: %w", err) } - return tx, e.client.ProcessTransaction(tx) -} -func (e *EthereumMercuryVerifierProxy) Verify(signedReport []byte, parameterPayload []byte, value *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if value != nil { - opts.Value = value - } - if err != nil { - return nil, err - } - tx, err := e.instance.Verify(opts, signedReport, parameterPayload) + instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumMockGASFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func (e *EthereumMercuryVerifierProxy) VerifyBulk(signedReports [][]byte, parameterPayload []byte, value *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if value != nil { - opts.Value = value - } +func LoadMockGASFeed(client *seth.Client, address common.Address) (MockGasFeed, error) { + abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) } - tx, err := e.instance.VerifyBulk(opts, signedReports, parameterPayload) + client.ContractStore.AddABI("MockGasFeed", *abi) + client.ContractStore.AddBIN("MockGasFeed", common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin)) + + instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumMockGASFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -func (e *EthereumMercuryVerifierProxy) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMultiCallContract(client *seth.Client) (common.Address, error) { + abi, err := abi.JSON(strings.NewReader(MultiCallABI)) if err != nil { - return nil, err + return common.Address{}, err } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called MercuryVerifierProxy.SetFeeManager()") + + data, err := client.DeployContract(client.NewTXOpts(), "MultiCall", abi, common.FromHex(MultiCallBIN)) if err != nil { - return nil, err + return common.Address{}, fmt.Errorf("MultiCall instance deployment have failed: %w", err) } - return tx, e.client.ProcessTransaction(tx) -} - -type EthereumMercuryFeeManager struct { - address common.Address - client blockchain.EVMClient - instance *fee_manager.FeeManager - l zerolog.Logger -} -func (e *EthereumMercuryFeeManager) Address() common.Address { - return e.address + return data.Address, nil } -func (e *EthereumMercuryFeeManager) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func LoadFunctionsCoordinator(seth *seth.Client, addr string) (FunctionsCoordinator, error) { + abi, err := functions_coordinator.FunctionsCoordinatorMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to get FunctionsCoordinator ABI: %w", err) } - tx, err := e.instance.UpdateSubscriberDiscount(opts, subscriber, feedId, token, discount) - e.l.Info().Err(err).Msg("Called EthereumMercuryFeeManager.UpdateSubscriberDiscount()") + seth.ContractStore.AddABI("FunctionsCoordinator", *abi) + seth.ContractStore.AddBIN("FunctionsCoordinator", common.FromHex(functions_coordinator.FunctionsCoordinatorMetaData.Bin)) + + instance, err := functions_coordinator.NewFunctionsCoordinator(common.HexToAddress(addr), seth.Client) if err != nil { - return nil, err + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to instantiate FunctionsCoordinator instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumFunctionsCoordinator{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err } -type EthereumMercuryRewardManager struct { +type EthereumFunctionsCoordinator struct { address common.Address - client blockchain.EVMClient - instance *reward_manager.RewardManager - l zerolog.Logger + client *seth.Client + instance *functions_coordinator.FunctionsCoordinator +} + +func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { + return e.instance.GetThresholdPublicKey(e.client.NewCallOpts()) } -func (e *EthereumMercuryRewardManager) Address() common.Address { - return e.address +func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { + return e.instance.GetDONPublicKey(e.client.NewCallOpts()) } -func (e *EthereumMercuryRewardManager) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func (e *EthereumFunctionsCoordinator) Address() string { + return e.address.Hex() +} + +func LoadFunctionsRouter(l zerolog.Logger, seth *seth.Client, addr string) (FunctionsRouter, error) { + abi, err := functions_router.FunctionsRouterMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to get FunctionsRouter ABI: %w", err) } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called EthereumMercuryRewardManager.SetFeeManager()") + seth.ContractStore.AddABI("FunctionsRouter", *abi) + seth.ContractStore.AddBIN("FunctionsRouter", common.FromHex(functions_router.FunctionsRouterMetaData.Bin)) + + instance, err := functions_router.NewFunctionsRouter(common.HexToAddress(addr), seth.Client) if err != nil { - return nil, err + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to instantiate FunctionsRouter instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumFunctionsRouter{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + l: l, + }, err } -type EthereumWERC20Mock struct { +type EthereumFunctionsRouter struct { address common.Address - client blockchain.EVMClient - instance *werc20_mock.WERC20Mock + client *seth.Client + instance *functions_router.FunctionsRouter l zerolog.Logger } -func (e *EthereumWERC20Mock) Address() common.Address { - return e.address +func (e *EthereumFunctionsRouter) Address() string { + return e.address.Hex() } -func (e *EthereumWERC20Mock) Approve(to string, amount *big.Int) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - e.l.Info(). - Str("From", e.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("Approving LINK Transfer") - tx, err := e.instance.Approve(opts, common.HexToAddress(to), amount) +func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { + tx, err := e.client.Decode(e.instance.CreateSubscriptionWithConsumer(e.client.NewTXOpts(), common.HexToAddress(consumer))) if err != nil { - return err + return 0, err } - return e.client.ProcessTransaction(tx) -} -func (e *EthereumWERC20Mock) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, + if tx.Receipt == nil { + return 0, errors.New("transaction did not err, but the receipt is nil") } - balance, err := e.instance.BalanceOf(opts, common.HexToAddress(addr)) - if err != nil { - return nil, err + for _, l := range tx.Receipt.Logs { + e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() } - return balance, nil -} + topicsMap := map[string]interface{}{} -func (e *EthereumWERC20Mock) Transfer(to string, amount *big.Int) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) + fabi, err := abi.JSON(strings.NewReader(functions_router.FunctionsRouterABI)) if err != nil { - return err + return 0, err } - e.l.Info(). - Str("From", e.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("EthereumWERC20Mock.Transfer()") - tx, err := e.instance.Transfer(opts, common.HexToAddress(to), amount) - if err != nil { - return err + for _, ev := range fabi.Events { + e.l.Info().Str("EventName", ev.Name).Send() + } + topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} + topicOneHash := []common.Hash{tx.Receipt.Logs[0].Topics[1:][0]} + if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { + return 0, fmt.Errorf("failed to decode topic value, err: %w", err) + } + e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send() + if topicsMap["subscriptionId"] == 0 { + return 0, fmt.Errorf("failed to decode subscription ID after creation") } - return e.client.ProcessTransaction(tx) + return topicsMap["subscriptionId"].(uint64), nil } -func (e *EthereumWERC20Mock) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployFunctionsLoadTestClient(seth *seth.Client, router string) (FunctionsLoadTestClient, error) { + operatorAbi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) } - e.l.Info(). - Str("account", account.Hex()). - Str("amount", amount.String()). - Msg("EthereumWERC20Mock.Mint()") - tx, err := e.instance.Mint(opts, account, amount) + data, err := seth.DeployContract(seth.NewTXOpts(), "FunctionsLoadTestClient", *operatorAbi, common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin), common.HexToAddress(router)) if err != nil { - return tx, err + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("FunctionsLoadTestClient instance deployment have failed: %w", err) } - return tx, e.client.ProcessTransaction(tx) -} -func ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkK8sClient) []ChainlinkNodeWithKeysAndAddress { - var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) - for i, node := range k8sNodes { - nodesAsInterface[i] = node + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(data.Address, seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) } - return nodesAsInterface + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: data.Address, + }, nil } -func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { - var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) - for i, node := range k8sNodes { - nodesAsInterface[i] = node +// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance +func LoadFunctionsLoadTestClient(seth *seth.Client, addr string) (FunctionsLoadTestClient, error) { + abi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) } + seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) + seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) - return nodesAsInterface + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) + } + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err } -func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract - } +type EthereumFunctionsLoadTestClient struct { + address common.Address + client *seth.Client + instance *functions_load_test_client.FunctionsLoadTestClient +} - return contractsAsInterface +func (e *EthereumFunctionsLoadTestClient) Address() string { + return e.address.Hex() } -func V1OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregator) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract +func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { + lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(e.client.NewCallOpts()) + if err != nil { + return nil, err } + return &EthereumFunctionsLoadStats{ + LastRequestID: string(Bytes32ToSlice(lr)), + LastResponse: string(lbody), + LastError: string(lerr), + Total: total, + Succeeded: succeeded, + Errored: errored, + Empty: empty, + }, nil +} - return contractsAsInterface +func (e *EthereumFunctionsLoadTestClient) ResetStats() error { + _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) + return err } -func GetRegistryContractABI(version contractsethereum.KeeperRegistryVersion) (*abi.ABI, error) { - var ( - contractABI *abi.ABI - err error - ) - switch version { - case contractsethereum.RegistryVersion_1_0, contractsethereum.RegistryVersion_1_1: - contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_1_2: - contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_1_3: - contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_0: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_1: - contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_2: - contractABI, err = iregistry22.IAutomationRegistryMasterMetaData.GetAbi() - default: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() - } +func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequest(e.client.NewTXOpts(), times, source, encryptedSecretsReferences, args, subscriptionId, jobId)) + return err +} - return contractABI, err +func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequestWithDONHostedSecrets(e.client.NewTXOpts(), times, source, slotID, slotVersion, args, subscriptionId, donID)) + return err } diff --git a/integration-tests/contracts/etherem_contracts_atlas_seth.go b/integration-tests/contracts/ethereum_contracts_atlas.go similarity index 100% rename from integration-tests/contracts/etherem_contracts_atlas_seth.go rename to integration-tests/contracts/ethereum_contracts_atlas.go diff --git a/integration-tests/contracts/ethereum_contracts_automation_seth.go b/integration-tests/contracts/ethereum_contracts_automation.go similarity index 99% rename from integration-tests/contracts/ethereum_contracts_automation_seth.go rename to integration-tests/contracts/ethereum_contracts_automation.go index 5f5bc0eaf06..13cad7ffefb 100644 --- a/integration-tests/contracts/ethereum_contracts_automation_seth.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -150,7 +150,7 @@ func (v *EthereumKeeperRegistry) Address() string { } func (v *EthereumKeeperRegistry) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { @@ -1575,7 +1575,7 @@ func (v *EthereumKeeperRegistrar) Address() string { } func (v *EthereumKeeperRegistrar) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } // EncodeRegisterRequest encodes register request to call it through link token TransferAndCall @@ -2008,7 +2008,7 @@ func (v *EthereumUpkeepCounter) Address() string { } func (v *EthereumUpkeepCounter) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumUpkeepCounter) Counter(ctx context.Context) (*big.Int, error) { return v.consumer.Counter(&bind.CallOpts{ @@ -2065,7 +2065,7 @@ func (v *EthereumUpkeepPerformCounterRestrictive) Address() string { } func (v *EthereumUpkeepPerformCounterRestrictive) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumUpkeepPerformCounterRestrictive) Counter(ctx context.Context) (*big.Int, error) { return v.consumer.GetCountPerforms(&bind.CallOpts{ @@ -2159,7 +2159,7 @@ func (v *EthereumKeeperConsumerPerformance) Address() string { } func (v *EthereumKeeperConsumerPerformance) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumKeeperConsumerPerformance) CheckEligible(ctx context.Context) (bool, error) { @@ -2278,7 +2278,7 @@ func (v *EthereumAutomationConsumerBenchmark) Address() string { } func (v *EthereumAutomationConsumerBenchmark) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumAutomationConsumerBenchmark) CheckEligible(ctx context.Context, id *big.Int, _range *big.Int, firstEligibleBuffer *big.Int) (bool, error) { diff --git a/integration-tests/contracts/ethereum_contracts_seth.go b/integration-tests/contracts/ethereum_contracts_seth.go deleted file mode 100644 index 803a0a3bcec..00000000000 --- a/integration-tests/contracts/ethereum_contracts_seth.go +++ /dev/null @@ -1,1330 +0,0 @@ -package contracts - -import ( - "context" - "encoding/hex" - "errors" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" -) - -// EthereumOffchainAggregator represents the offchain aggregation contract -type EthereumOffchainAggregator struct { - client *seth.Client - ocr *offchainaggregator.OffchainAggregator - address *common.Address - l zerolog.Logger -} - -func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { - abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregator", *abi) - seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) - - ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregator{ - client: seth, - ocr: ocr, - address: &contractAddress, - l: l, - }, nil -} - -func DeployOffchainAggregator(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregator, error) { - abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - - ocrDeploymentData, err := seth.DeployContract( - seth.NewTXOpts(), - "OffChainAggregator", - *abi, - common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin), - offchainOptions.MaximumGasPrice, - offchainOptions.ReasonableGasPrice, - offchainOptions.MicroLinkPerEth, - offchainOptions.LinkGweiPerObservation, - offchainOptions.LinkGweiPerTransmission, - linkTokenAddress, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - - ocr, err := offchainaggregator.NewOffchainAggregator(ocrDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregator{ - client: seth, - ocr: ocr, - address: &ocrDeploymentData.Address, - l: l, - }, nil -} - -// SetPayees sets wallets for the contract to pay out to? -func (o *EthereumOffchainAggregator) SetPayees( - transmitters, payees []string, -) error { - var transmittersAddr, payeesAddr []common.Address - for _, tr := range transmitters { - transmittersAddr = append(transmittersAddr, common.HexToAddress(tr)) - } - for _, p := range payees { - payeesAddr = append(payeesAddr, common.HexToAddress(p)) - } - - o.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCR Address", o.Address()). - Msg("Setting OCR Payees") - - _, err := o.client.Decode(o.ocr.SetPayees(o.client.NewTXOpts(), transmittersAddr, payeesAddr)) - return err -} - -// SetConfig sets the payees and the offchain reporting protocol configuration -func (o *EthereumOffchainAggregator) SetConfig( - chainlinkNodes []ChainlinkNodeWithKeysAndAddress, - ocrConfig OffChainAggregatorConfig, - transmitters []common.Address, -) error { - // Gather necessary addresses and keys from our chainlink nodes to properly configure the OCR contract - log.Info().Str("Contract Address", o.address.Hex()).Msg("Configuring OCR Contract") - for i, node := range chainlinkNodes { - ocrKeys, err := node.MustReadOCRKeys() - if err != nil { - return err - } - if len(ocrKeys.Data) == 0 { - return fmt.Errorf("no OCR keys found for node %v", node) - } - primaryOCRKey := ocrKeys.Data[0] - p2pKeys, err := node.MustReadP2PKeys() - if err != nil { - return err - } - primaryP2PKey := p2pKeys.Data[0] - - // Need to convert the key representations - var onChainSigningAddress [20]byte - var configPublicKey [32]byte - offchainSigningAddress, err := hex.DecodeString(primaryOCRKey.Attributes.OffChainPublicKey) - if err != nil { - return err - } - decodeConfigKey, err := hex.DecodeString(primaryOCRKey.Attributes.ConfigPublicKey) - if err != nil { - return err - } - - // https://stackoverflow.com/questions/8032170/how-to-assign-string-to-bytes-array - copy(onChainSigningAddress[:], common.HexToAddress(primaryOCRKey.Attributes.OnChainSigningAddress).Bytes()) - copy(configPublicKey[:], decodeConfigKey) - - oracleIdentity := ocrConfigHelper.OracleIdentity{ - TransmitAddress: transmitters[i], - OnChainSigningAddress: onChainSigningAddress, - PeerID: primaryP2PKey.Attributes.PeerID, - OffchainPublicKey: offchainSigningAddress, - } - oracleIdentityExtra := ocrConfigHelper.OracleIdentityExtra{ - OracleIdentity: oracleIdentity, - SharedSecretEncryptionPublicKey: ocrTypes.SharedSecretEncryptionPublicKey(configPublicKey), - } - - ocrConfig.OracleIdentities = append(ocrConfig.OracleIdentities, oracleIdentityExtra) - } - - signers, transmitters, threshold, encodedConfigVersion, encodedConfig, err := ocrConfigHelper.ContractSetConfigArgs( - ocrConfig.DeltaProgress, - ocrConfig.DeltaResend, - ocrConfig.DeltaRound, - ocrConfig.DeltaGrace, - ocrConfig.DeltaC, - ocrConfig.AlphaPPB, - ocrConfig.DeltaStage, - ocrConfig.RMax, - ocrConfig.S, - ocrConfig.OracleIdentities, - ocrConfig.F, - ) - if err != nil { - return err - } - - // fails with error setting OCR config for contract '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82': both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified - // but we only have gasPrice set... It also fails with the same error when we enable EIP-1559 - // fails when we wait for it to be minted, inside the wrapper there's no error when we call it, so it must be something inside smart contract - // that's reverting it and maybe the error message is completely off - _, err = o.client.Decode(o.ocr.SetConfig(o.client.NewTXOpts(), signers, transmitters, threshold, encodedConfigVersion, encodedConfig)) - return err -} - -// RequestNewRound requests the OCR contract to create a new round -func (o *EthereumOffchainAggregator) RequestNewRound() error { - o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") - _, err := o.client.Decode(o.ocr.RequestNewRound(o.client.NewTXOpts())) - return err -} - -// GetLatestAnswer returns the latest answer from the OCR contract -func (o *EthereumOffchainAggregator) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - return o.ocr.LatestAnswer(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }) -} - -func (o *EthereumOffchainAggregator) Address() string { - return o.address.Hex() -} - -// GetLatestRound returns data from the latest round -func (o *EthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { - roundData, err := o.ocr.LatestRoundData(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, err -} - -func (o *EthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := o.ocr.LatestRoundData(o.client.NewCallOpts()) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil -} - -// GetRound retrieves an OCR round by the round ID -func (o *EthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - roundData, err := o.ocr.GetRoundData(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }, roundID) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, nil -} - -// ParseEventAnswerUpdated parses the log for event AnswerUpdated -func (o *EthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { - return o.ocr.ParseAnswerUpdated(eventLog) -} - -// LegacyEthereumOperatorFactory represents operator factory contract -type EthereumOperatorFactory struct { - address *common.Address - client *seth.Client - operatorFactory *operator_factory.OperatorFactory -} - -func DeployEthereumOperatorFactory(seth *seth.Client, linkTokenAddress common.Address) (EthereumOperatorFactory, error) { - abi, err := operator_factory.OperatorFactoryMetaData.GetAbi() - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("failed to get OperatorFactory ABI: %w", err) - } - operatorData, err := seth.DeployContract(seth.NewTXOpts(), "OperatorFactory", *abi, common.FromHex(operator_factory.OperatorFactoryMetaData.Bin), linkTokenAddress) - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("OperatorFactory instance deployment have failed: %w", err) - } - - operatorFactory, err := operator_factory.NewOperatorFactory(operatorData.Address, seth.Client) - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("failed to instantiate OperatorFactory instance: %w", err) - } - - return EthereumOperatorFactory{ - address: &operatorData.Address, - client: seth, - operatorFactory: operatorFactory, - }, nil -} - -func (e *EthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { - return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) -} - -func (e *EthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { - return e.operatorFactory.ParseOperatorCreated(eventLog) -} - -func (e *EthereumOperatorFactory) Address() string { - return e.address.Hex() -} - -func (e *EthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { - return e.operatorFactory.DeployNewOperatorAndForwarder(e.client.NewTXOpts()) -} - -// EthereumOperator represents operator contract -type EthereumOperator struct { - address *common.Address - client *seth.Client - operator *operator_wrapper.Operator - l zerolog.Logger -} - -func LoadEthereumOperator(logger zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOperator, error) { - - abi, err := operator_wrapper.OperatorMetaData.GetAbi() - if err != nil { - return EthereumOperator{}, err - } - seth.ContractStore.AddABI("EthereumOperator", *abi) - seth.ContractStore.AddBIN("EthereumOperator", common.FromHex(operator_wrapper.OperatorMetaData.Bin)) - - operator, err := operator_wrapper.NewOperator(contractAddress, seth.Client) - if err != nil { - return EthereumOperator{}, err - } - - return EthereumOperator{ - address: &contractAddress, - client: seth, - operator: operator, - l: logger, - }, nil -} - -func (e *EthereumOperator) Address() string { - return e.address.Hex() -} - -func (e *EthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { - e.l.Info(). - Str("ForwardersAddresses", fmt.Sprint(forwarders)). - Str("EoaAddresses", fmt.Sprint(eoa)). - Msg("Accepting Authorized Receivers") - _, err := e.client.Decode(e.operator.AcceptAuthorizedReceivers(e.client.NewTXOpts(), forwarders, eoa)) - return err -} - -// EthereumAuthorizedForwarder represents authorized forwarder contract -type EthereumAuthorizedForwarder struct { - address *common.Address - client *seth.Client - authorizedForwarder *authorized_forwarder.AuthorizedForwarder -} - -func LoadEthereumAuthorizedForwarder(seth *seth.Client, contractAddress common.Address) (EthereumAuthorizedForwarder, error) { - abi, err := authorized_forwarder.AuthorizedForwarderMetaData.GetAbi() - if err != nil { - return EthereumAuthorizedForwarder{}, err - } - seth.ContractStore.AddABI("AuthorizedForwarder", *abi) - seth.ContractStore.AddBIN("AuthorizedForwarder", common.FromHex(authorized_forwarder.AuthorizedForwarderMetaData.Bin)) - - authorizedForwarder, err := authorized_forwarder.NewAuthorizedForwarder(contractAddress, seth.Client) - if err != nil { - return EthereumAuthorizedForwarder{}, fmt.Errorf("failed to instantiate AuthorizedForwarder instance: %w", err) - } - - return EthereumAuthorizedForwarder{ - address: &contractAddress, - client: seth, - authorizedForwarder: authorizedForwarder, - }, nil -} - -// Owner return authorized forwarder owner address -func (e *EthereumAuthorizedForwarder) Owner(_ context.Context) (string, error) { - owner, err := e.authorizedForwarder.Owner(e.client.NewCallOpts()) - - return owner.Hex(), err -} - -func (e *EthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - } - authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) - if err != nil { - return nil, err - } - var sendersAddrs []string - for _, o := range authorizedSenders { - sendersAddrs = append(sendersAddrs, o.Hex()) - } - return sendersAddrs, nil -} - -func (e *EthereumAuthorizedForwarder) Address() string { - return e.address.Hex() -} - -type EthereumOffchainAggregatorV2 struct { - address *common.Address - client *seth.Client - contract *ocr2aggregator.OCR2Aggregator - l zerolog.Logger -} - -func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) - seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - - ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregatorV2{ - client: seth, - contract: ocr2, - address: &contractAddress, - l: l, - }, nil -} - -func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) - seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - - ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *oAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), - linkTokenAddress, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description, - ) - - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - - ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregatorV2{ - client: seth, - contract: ocr2, - address: &ocrDeploymentData2.Address, - l: l, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) Address() string { - return e.address.Hex() -} - -func (e *EthereumOffchainAggregatorV2) RequestNewRound() error { - _, err := e.client.Decode(e.contract.RequestNewRound(e.client.NewTXOpts())) - return err -} - -func (e *EthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - return e.contract.LatestAnswer(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -func (e *EthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { - data, err := e.contract.LatestRoundData(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - data, err := e.contract.GetRoundData(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }, roundID) - if err != nil { - return nil, err - } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { - e.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCRv2 Address", e.Address()). - Msg("Setting OCRv2 Payees") - - var addTransmitters, addrPayees []common.Address - for _, t := range transmitters { - addTransmitters = append(addTransmitters, common.HexToAddress(t)) - } - for _, p := range payees { - addrPayees = append(addrPayees, common.HexToAddress(p)) - } - - _, err := e.client.Decode(e.contract.SetPayees(e.client.NewTXOpts(), addTransmitters, addrPayees)) - return err -} - -func (e *EthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { - e.l.Info(). - Str("Address", e.Address()). - Interface("Signers", ocrConfig.Signers). - Interface("Transmitters", ocrConfig.Transmitters). - Uint8("F", ocrConfig.F). - Bytes("OnchainConfig", ocrConfig.OnchainConfig). - Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). - Bytes("OffchainConfig", ocrConfig.OffchainConfig). - Msg("Setting OCRv2 Config") - - _, err := e.client.Decode(e.contract.SetConfig( - e.client.NewTXOpts(), - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - )) - return err -} - -func (e *EthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { - return e.contract.ParseAnswerUpdated(log) -} - -// EthereumLinkToken represents a LinkToken address -type EthereumLinkToken struct { - client *seth.Client - instance *link_token_interface.LinkToken - address common.Address - l zerolog.Logger -} - -func DeployLinkTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumLinkToken, error) { - linkTokenAbi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) - } - linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("LinkToken instance deployment have failed: %w", err) - } - - linkToken, err := link_token_interface.NewLinkToken(linkDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) - } - - return &EthereumLinkToken{ - client: client, - instance: linkToken, - address: linkDeploymentData.Address, - l: l, - }, nil -} - -func LoadLinkTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumLinkToken, error) { - abi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) - } - - client.ContractStore.AddABI("LinkToken", *abi) - client.ContractStore.AddBIN("LinkToken", common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) - - linkToken, err := link_token_interface.NewLinkToken(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) - } - - return &EthereumLinkToken{ - client: client, - instance: linkToken, - address: address, - l: l, - }, nil -} - -// Fund the LINK Token contract with ETH to distribute the token -func (l *EthereumLinkToken) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") -} - -func (l *EthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - return l.instance.BalanceOf(&bind.CallOpts{ - From: l.client.Addresses[0], - Context: ctx, - }, common.HexToAddress(addr)) - -} - -// Name returns the name of the link token -func (l *EthereumLinkToken) Name(ctx context.Context) (string, error) { - return l.instance.Name(&bind.CallOpts{ - From: l.client.Addresses[0], - Context: ctx, - }) -} - -func (l *EthereumLinkToken) Address() string { - return l.address.Hex() -} - -func (l *EthereumLinkToken) Approve(to string, amount *big.Int) error { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Approving LINK Transfer") - _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) - return err -} - -func (l *EthereumLinkToken) Transfer(to string, amount *big.Int) error { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring LINK") - _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) - return err -} - -func (l *EthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring and Calling LINK") - decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXOpts(), common.HexToAddress(to), amount, data)) - if err != nil { - return nil, err - } - return decodedTx.Transaction, nil -} - -func (l *EthereumLinkToken) TransferAndCallFromKey(to string, amount *big.Int, data []byte, keyNum int) (*types.Transaction, error) { - l.l.Info(). - Str("From", l.client.Addresses[keyNum].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring and Calling LINK") - decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXKeyOpts(keyNum), common.HexToAddress(to), amount, data)) - if err != nil { - return nil, err - } - return decodedTx.Transaction, nil -} - -// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain -func DeployFluxAggregatorContract( - seth *seth.Client, - linkAddr string, - fluxOptions FluxAggregatorOptions, -) (FluxAggregator, error) { - abi, err := flux_aggregator_wrapper.FluxAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("failed to get FluxAggregator ABI: %w", err) - } - seth.ContractStore.AddABI("FluxAggregator", *abi) - seth.ContractStore.AddBIN("FluxAggregator", common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin)) - - fluxDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "FluxAggregator", *abi, common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin), - common.HexToAddress(linkAddr), - fluxOptions.PaymentAmount, - fluxOptions.Timeout, - fluxOptions.Validator, - fluxOptions.MinSubValue, - fluxOptions.MaxSubValue, - fluxOptions.Decimals, - fluxOptions.Description, - ) - - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("FluxAggregator instance deployment have failed: %w", err) - } - - flux, err := flux_aggregator_wrapper.NewFluxAggregator(fluxDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("failed to instantiate FluxAggregator instance: %w", err) - } - - return &EthereumFluxAggregator{ - client: seth, - address: &fluxDeploymentData.Address, - fluxAggregator: flux, - }, nil -} - -// EthereumFluxAggregator represents the basic flux aggregation contract -type EthereumFluxAggregator struct { - client *seth.Client - fluxAggregator *flux_aggregator_wrapper.FluxAggregator - address *common.Address -} - -func (f *EthereumFluxAggregator) Address() string { - return f.address.Hex() -} - -// Fund sends specified currencies to the contract -func (f *EthereumFluxAggregator) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -func (f *EthereumFluxAggregator) UpdateAvailableFunds() error { - _, err := f.client.Decode(f.fluxAggregator.UpdateAvailableFunds(f.client.NewTXOpts())) - return err -} - -func (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { - return f.fluxAggregator.PaymentAmount(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -func (f *EthereumFluxAggregator) RequestNewRound(context.Context) error { - _, err := f.client.Decode(f.fluxAggregator.RequestNewRound(f.client.NewTXOpts())) - return err -} - -// WatchSubmissionReceived subscribes to any submissions on a flux feed -func (f *EthereumFluxAggregator) WatchSubmissionReceived(_ context.Context, _ chan<- *SubmissionEvent) error { - panic("do not use this method, instead use XXXX") -} - -func (f *EthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { - _, err := f.client.Decode(f.fluxAggregator.SetRequesterPermissions(f.client.NewTXOpts(), addr, authorized, roundsDelay)) - return err -} - -func (f *EthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { - addresses, err := f.fluxAggregator.GetOracles(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - var oracleAddrs []string - for _, o := range addresses { - oracleAddrs = append(oracleAddrs, o.Hex()) - } - return oracleAddrs, nil -} - -func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { - return f.fluxAggregator.LatestRound(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -func (f *EthereumFluxAggregator) WithdrawPayment( - _ context.Context, - from common.Address, - to common.Address, - amount *big.Int) error { - _, err := f.client.Decode(f.fluxAggregator.WithdrawPayment(f.client.NewTXOpts(), from, to, amount)) - return err -} - -func (f *EthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { - return f.fluxAggregator.WithdrawablePayment(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }, addr) -} - -func (f *EthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { - return f.fluxAggregator.LatestRoundData(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -// GetContractData retrieves basic data for the flux aggregator contract -func (f *EthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { - opts := &bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - } - - allocated, err := f.fluxAggregator.AllocatedFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - available, err := f.fluxAggregator.AvailableFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - latestRound := RoundData(lr) - - oracles, err := f.fluxAggregator.GetOracles(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - return &FluxAggregatorData{ - AllocatedFunds: allocated, - AvailableFunds: available, - LatestRoundData: latestRound, - Oracles: oracles, - }, nil -} - -// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins -func (f *EthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { - _, err := f.client.Decode(f.fluxAggregator.ChangeOracles(f.client.NewTXOpts(), o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds)) - if err != nil { - return err - } - return err -} - -// Description returns the description of the flux aggregator contract -func (f *EthereumFluxAggregator) Description(ctxt context.Context) (string, error) { - return f.fluxAggregator.Description(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctxt, - }) -} - -func DeployOracle(seth *seth.Client, linkAddr string) (Oracle, error) { - abi, err := oracle_wrapper.OracleMetaData.GetAbi() - if err != nil { - return &EthereumOracle{}, fmt.Errorf("failed to get Oracle ABI: %w", err) - } - seth.ContractStore.AddABI("Oracle", *abi) - seth.ContractStore.AddBIN("Oracle", common.FromHex(oracle_wrapper.OracleMetaData.Bin)) - - oracleDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "Oracle", *abi, common.FromHex(oracle_wrapper.OracleMetaData.Bin), - common.HexToAddress(linkAddr), - ) - - if err != nil { - return &EthereumOracle{}, fmt.Errorf("Oracle instance deployment have failed: %w", err) - } - - oracle, err := oracle_wrapper.NewOracle(oracleDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumOracle{}, fmt.Errorf("Oracle to instantiate FluxAggregator instance: %w", err) - } - - return &EthereumOracle{ - client: seth, - address: &oracleDeploymentData.Address, - oracle: oracle, - }, nil -} - -// EthereumOracle oracle for "directrequest" job tests -type EthereumOracle struct { - address *common.Address - client *seth.Client - oracle *oracle_wrapper.Oracle -} - -func (e *EthereumOracle) Address() string { - return e.address.Hex() -} - -func (e *EthereumOracle) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -// SetFulfillmentPermission sets fulfillment permission for particular address -func (e *EthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { - _, err := e.client.Decode(e.oracle.SetFulfillmentPermission(e.client.NewTXOpts(), common.HexToAddress(address), allowed)) - return err -} - -func DeployAPIConsumer(seth *seth.Client, linkAddr string) (APIConsumer, error) { - abi, err := test_api_consumer_wrapper.TestAPIConsumerMetaData.GetAbi() - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("failed to get TestAPIConsumer ABI: %w", err) - } - seth.ContractStore.AddABI("TestAPIConsumer", *abi) - seth.ContractStore.AddBIN("TestAPIConsumer", common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin)) - - consumerDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "TestAPIConsumer", *abi, common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin), - common.HexToAddress(linkAddr), - ) - - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("TestAPIConsumer instance deployment have failed: %w", err) - } - - consumer, err := test_api_consumer_wrapper.NewTestAPIConsumer(consumerDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("failed to instantiate TestAPIConsumer instance: %w", err) - } - - return &EthereumAPIConsumer{ - client: seth, - address: &consumerDeploymentData.Address, - consumer: consumer, - }, nil -} - -// EthereumAPIConsumer API consumer for job type "directrequest" tests -type EthereumAPIConsumer struct { - address *common.Address - client *seth.Client - consumer *test_api_consumer_wrapper.TestAPIConsumer -} - -func (e *EthereumAPIConsumer) Address() string { - return e.address.Hex() -} - -func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { - return e.consumer.CurrentRoundID(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -func (e *EthereumAPIConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -func (e *EthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { - return e.consumer.Data(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -// CreateRequestTo creates request to an oracle for particular jobID with params -func (e *EthereumAPIConsumer) CreateRequestTo( - oracleAddr string, - jobID [32]byte, - payment *big.Int, - url string, - path string, - times *big.Int, -) error { - _, err := e.client.Decode(e.consumer.CreateRequestTo(e.client.NewTXOpts(), common.HexToAddress(oracleAddr), jobID, payment, url, path, times)) - return err -} - -// EthereumMockETHLINKFeed represents mocked ETH/LINK feed contract -type EthereumMockETHLINKFeed struct { - client *seth.Client - feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator - address *common.Address -} - -func (v *EthereumMockETHLINKFeed) Address() string { - return v.address.Hex() -} - -func (v *EthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: v.client.Addresses[0], - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.Ans, nil -} - -func (v *EthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: v.client.Addresses[0], - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil -} - -func DeployMockETHLINKFeed(client *seth.Client, answer *big.Int) (MockETHLINKFeed, error) { - abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "MockETHLINKFeed", *abi, common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin), answer) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("MockETHLINKFeed instance deployment have failed: %w", err) - } - - instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) - } - - return &EthereumMockETHLINKFeed{ - address: &data.Address, - client: client, - feed: instance, - }, nil -} - -func LoadMockETHLINKFeed(client *seth.Client, address common.Address) (MockETHLINKFeed, error) { - abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) - } - client.ContractStore.AddABI("MockETHLINKFeed", *abi) - client.ContractStore.AddBIN("MockETHLINKFeed", common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin)) - - instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) - } - - return &EthereumMockETHLINKFeed{ - address: &address, - client: client, - feed: instance, - }, nil -} - -// EthereumMockGASFeed represents mocked Gas feed contract -type EthereumMockGASFeed struct { - client *seth.Client - feed *mock_gas_aggregator_wrapper.MockGASAggregator - address *common.Address -} - -func (v *EthereumMockGASFeed) Address() string { - return v.address.Hex() -} - -func DeployMockGASFeed(client *seth.Client, answer *big.Int) (MockGasFeed, error) { - abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "MockGasFeed", *abi, common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin), answer) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("MockGasFeed instance deployment have failed: %w", err) - } - - instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) - } - - return &EthereumMockGASFeed{ - address: &data.Address, - client: client, - feed: instance, - }, nil -} - -func LoadMockGASFeed(client *seth.Client, address common.Address) (MockGasFeed, error) { - abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) - } - client.ContractStore.AddABI("MockGasFeed", *abi) - client.ContractStore.AddBIN("MockGasFeed", common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin)) - - instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) - } - - return &EthereumMockGASFeed{ - address: &address, - client: client, - feed: instance, - }, nil -} - -func DeployMultiCallContract(client *seth.Client) (common.Address, error) { - abi, err := abi.JSON(strings.NewReader(MultiCallABI)) - if err != nil { - return common.Address{}, err - } - - data, err := client.DeployContract(client.NewTXOpts(), "MultiCall", abi, common.FromHex(MultiCallBIN)) - if err != nil { - return common.Address{}, fmt.Errorf("MultiCall instance deployment have failed: %w", err) - } - - return data.Address, nil -} - -func LoadFunctionsCoordinator(seth *seth.Client, addr string) (FunctionsCoordinator, error) { - abi, err := functions_coordinator.FunctionsCoordinatorMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to get FunctionsCoordinator ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsCoordinator", *abi) - seth.ContractStore.AddBIN("FunctionsCoordinator", common.FromHex(functions_coordinator.FunctionsCoordinatorMetaData.Bin)) - - instance, err := functions_coordinator.NewFunctionsCoordinator(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to instantiate FunctionsCoordinator instance: %w", err) - } - - return &EthereumFunctionsCoordinator{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - }, err -} - -type EthereumFunctionsCoordinator struct { - address common.Address - client *seth.Client - instance *functions_coordinator.FunctionsCoordinator -} - -func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { - return e.instance.GetThresholdPublicKey(e.client.NewCallOpts()) -} - -func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { - return e.instance.GetDONPublicKey(e.client.NewCallOpts()) -} - -func (e *EthereumFunctionsCoordinator) Address() string { - return e.address.Hex() -} - -func LoadFunctionsRouter(l zerolog.Logger, seth *seth.Client, addr string) (FunctionsRouter, error) { - abi, err := functions_router.FunctionsRouterMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsRouter{}, fmt.Errorf("failed to get FunctionsRouter ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsRouter", *abi) - seth.ContractStore.AddBIN("FunctionsRouter", common.FromHex(functions_router.FunctionsRouterMetaData.Bin)) - - instance, err := functions_router.NewFunctionsRouter(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsRouter{}, fmt.Errorf("failed to instantiate FunctionsRouter instance: %w", err) - } - - return &EthereumFunctionsRouter{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - l: l, - }, err -} - -type EthereumFunctionsRouter struct { - address common.Address - client *seth.Client - instance *functions_router.FunctionsRouter - l zerolog.Logger -} - -func (e *EthereumFunctionsRouter) Address() string { - return e.address.Hex() -} - -func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { - tx, err := e.client.Decode(e.instance.CreateSubscriptionWithConsumer(e.client.NewTXOpts(), common.HexToAddress(consumer))) - if err != nil { - return 0, err - } - - if tx.Receipt == nil { - return 0, errors.New("transaction did not err, but the receipt is nil") - } - for _, l := range tx.Receipt.Logs { - e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() - } - topicsMap := map[string]interface{}{} - - fabi, err := abi.JSON(strings.NewReader(functions_router.FunctionsRouterABI)) - if err != nil { - return 0, err - } - for _, ev := range fabi.Events { - e.l.Info().Str("EventName", ev.Name).Send() - } - topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} - topicOneHash := []common.Hash{tx.Receipt.Logs[0].Topics[1:][0]} - if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { - return 0, fmt.Errorf("failed to decode topic value, err: %w", err) - } - e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send() - if topicsMap["subscriptionId"] == 0 { - return 0, fmt.Errorf("failed to decode subscription ID after creation") - } - return topicsMap["subscriptionId"].(uint64), nil -} - -func DeployFunctionsLoadTestClient(seth *seth.Client, router string) (FunctionsLoadTestClient, error) { - operatorAbi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) - } - data, err := seth.DeployContract(seth.NewTXOpts(), "FunctionsLoadTestClient", *operatorAbi, common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin), common.HexToAddress(router)) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("FunctionsLoadTestClient instance deployment have failed: %w", err) - } - - instance, err := functions_load_test_client.NewFunctionsLoadTestClient(data.Address, seth.Client) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) - } - - return &EthereumFunctionsLoadTestClient{ - client: seth, - instance: instance, - address: data.Address, - }, nil -} - -// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance -func LoadFunctionsLoadTestClient(seth *seth.Client, addr string) (FunctionsLoadTestClient, error) { - abi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) - seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) - - instance, err := functions_load_test_client.NewFunctionsLoadTestClient(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) - } - - return &EthereumFunctionsLoadTestClient{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - }, err -} - -type EthereumFunctionsLoadTestClient struct { - address common.Address - client *seth.Client - instance *functions_load_test_client.FunctionsLoadTestClient -} - -func (e *EthereumFunctionsLoadTestClient) Address() string { - return e.address.Hex() -} - -func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { - lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(e.client.NewCallOpts()) - if err != nil { - return nil, err - } - return &EthereumFunctionsLoadStats{ - LastRequestID: string(Bytes32ToSlice(lr)), - LastResponse: string(lbody), - LastError: string(lerr), - Total: total, - Succeeded: succeeded, - Errored: errored, - Empty: empty, - }, nil -} - -func (e *EthereumFunctionsLoadTestClient) ResetStats() error { - _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) - return err -} - -func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { - _, err := e.client.Decode(e.instance.SendRequest(e.client.NewTXOpts(), times, source, encryptedSecretsReferences, args, subscriptionId, jobId)) - return err -} - -func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { - _, err := e.client.Decode(e.instance.SendRequestWithDONHostedSecrets(e.client.NewTXOpts(), times, source, slotID, slotVersion, args, subscriptionId, donID)) - return err -} diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 31c3cb32dc7..b933c18df0c 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -2,49 +2,19 @@ package contracts import ( "context" - "errors" - "fmt" "math/big" - "strconv" - "strings" - "time" - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" goabi "github.com/umbracle/ethgo/abi" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_chain_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" ) var compatibleUtils = cltypes.MustGetABI(ac.AutomationCompatibleUtilsABI) @@ -180,74 +150,24 @@ type KeeperRegistrySettings struct { RegistryVersion ethereum.KeeperRegistryVersion } -// KeeperRegistrarSettings represents settings for registrar contract -type KeeperRegistrarSettings struct { - AutoApproveConfigType uint8 - AutoApproveMaxAllowed uint16 - RegistryAddr string - MinLinkJuels *big.Int -} - -// KeeperInfo keeper status and balance info -type KeeperInfo struct { - Payee string - Active bool - Balance *big.Int -} - -// UpkeepInfo keeper target info -type UpkeepInfo struct { - Target string - ExecuteGas uint32 - CheckData []byte - Balance *big.Int - LastKeeper string - Admin string - MaxValidBlocknumber uint64 - LastPerformBlockNumber uint32 - AmountSpent *big.Int - Paused bool - OffchainConfig []byte -} - -// LegacyEthereumKeeperRegistry represents keeper registry contract -type LegacyEthereumKeeperRegistry struct { - client blockchain.EVMClient - version ethereum.KeeperRegistryVersion - registry1_1 *keeper_registry_wrapper1_1.KeeperRegistry - registry1_2 *keeper_registry_wrapper1_2.KeeperRegistry - registry1_3 *keeper_registry_wrapper1_3.KeeperRegistry - registry2_0 *keeper_registry_wrapper2_0.KeeperRegistry - registry2_1 *i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMaster - registry2_2 *i_automation_registry_master_wrapper_2_2.IAutomationRegistryMaster - chainModule *i_chain_module.IChainModule - address *common.Address - l zerolog.Logger -} - -func (v *LegacyEthereumKeeperRegistry) ReorgProtectionEnabled() bool { - chainId := v.client.GetChainID().Uint64() - // reorg protection is disabled in polygon zkEVM and Scroll bc currently there is no way to get the block hash onchain - return v.version != ethereum.RegistryVersion_2_2 || (chainId != 1101 && chainId != 1442 && chainId != 2442 && chainId != 534352 && chainId != 534351) -} - -func (v *LegacyEthereumKeeperRegistry) ChainModuleAddress() common.Address { - if v.version == ethereum.RegistryVersion_2_2 { - return v.chainModule.Address() - } - return common.Address{} -} - -func (v *LegacyEthereumKeeperRegistry) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperRegistry) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) +func (rcs *KeeperRegistrySettings) Encode20OnchainConfig(registrar string) []byte { + configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)") + onchainConfig, _ := goabi.Encode(map[string]interface{}{ + "paymentPremiumPPB": rcs.PaymentPremiumPPB, + "flatFeeMicroLink": rcs.FlatFeeMicroLINK, + "checkGasLimit": rcs.CheckGasLimit, + "stalenessSeconds": rcs.StalenessSeconds, + "gasCeilingMultiplier": rcs.GasCeilingMultiplier, + "minUpkeepSpend": rcs.MinUpkeepSpend, + "maxPerformGas": rcs.MaxPerformGas, + "maxCheckDataSize": rcs.MaxCheckDataSize, + "maxPerformDataSize": rcs.MaxPerformDataSize, + "fallbackGasPrice": rcs.FallbackGasPrice, + "fallbackLinkPrice": rcs.FallbackLinkPrice, + "transcoder": common.Address{}, + "registrar": registrar, + }, configType) + return onchainConfig } func (rcs *KeeperRegistrySettings) Create22OnchainConfig(registrar string, registryOwnerAddress, chainModuleAddress common.Address, reorgProtectionEnabled bool) i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig { @@ -292,2077 +212,32 @@ func (rcs *KeeperRegistrySettings) Create21OnchainConfig(registrar string, regis } } -func (rcs *KeeperRegistrySettings) Encode20OnchainConfig(registrar string) []byte { - configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)") - onchainConfig, _ := goabi.Encode(map[string]interface{}{ - "paymentPremiumPPB": rcs.PaymentPremiumPPB, - "flatFeeMicroLink": rcs.FlatFeeMicroLINK, - "checkGasLimit": rcs.CheckGasLimit, - "stalenessSeconds": rcs.StalenessSeconds, - "gasCeilingMultiplier": rcs.GasCeilingMultiplier, - "minUpkeepSpend": rcs.MinUpkeepSpend, - "maxPerformGas": rcs.MaxPerformGas, - "maxCheckDataSize": rcs.MaxCheckDataSize, - "maxPerformDataSize": rcs.MaxPerformDataSize, - "fallbackGasPrice": rcs.FallbackGasPrice, - "fallbackLinkPrice": rcs.FallbackLinkPrice, - "transcoder": common.Address{}, - "registrar": registrar, - }, configType) - return onchainConfig -} - -func (v *LegacyEthereumKeeperRegistry) RegistryOwnerAddress() common.Address { - callOpts := &bind.CallOpts{ - Pending: false, - } - - //nolint: exhaustive - switch v.version { - case ethereum.RegistryVersion_2_2: - ownerAddress, _ := v.registry2_2.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_2_1: - ownerAddress, _ := v.registry2_1.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_2_0: - ownerAddress, _ := v.registry2_0.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1, ethereum.RegistryVersion_1_2, ethereum.RegistryVersion_1_3: - return common.HexToAddress(v.client.GetDefaultWallet().Address()) - } - - return common.HexToAddress(v.client.GetDefaultWallet().Address()) -} - -func (v *LegacyEthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - switch v.version { - case ethereum.RegistryVersion_2_1: - tx, err := v.registry2_1.SetConfigTypeSafe(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.TypedOnchainConfig21, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - tx, err := v.registry2_2.SetConfigTypeSafe(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.TypedOnchainConfig22, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetConfigTypeSafe is not supported in keeper registry version %d", v.version) - } -} - -func (v *LegacyEthereumKeeperRegistry) SetConfig(config KeeperRegistrySettings, ocrConfig OCRv2Config) error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - callOpts := bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: nil, - } - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err := v.registry1_1.SetConfig( - txOpts, - config.PaymentPremiumPPB, - config.FlatFeeMicroLINK, - config.BlockCountPerTurn, - config.CheckGasLimit, - config.StalenessSeconds, - config.GasCeilingMultiplier, - config.FallbackGasPrice, - config.FallbackLinkPrice, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - - tx, err := v.registry1_2.SetConfig(txOpts, keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - }) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - - tx, err := v.registry1_3.SetConfig(txOpts, keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - }) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - tx, err := v.registry2_0.SetConfig(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("registry version 2.1 and 2.2 must use setConfigTypeSafe function") - default: - return fmt.Errorf("keeper registry version %d is not supported", v.version) - } -} - -// Pause pauses the registry. -func (v *LegacyEthereumKeeperRegistry) Pause() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - } - - return fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// Migrate performs a migration of the given upkeep ids to the specific destination passed as parameter. -func (v *LegacyEthereumKeeperRegistry) Migrate(upkeepIDs []*big.Int, destinationAddress common.Address) error { - if v.version != ethereum.RegistryVersion_1_2 { - return fmt.Errorf("migration of upkeeps is only available for version 1.2 of the registries") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_2.MigrateUpkeeps(txOpts, upkeepIDs, destinationAddress) - if err != nil { - return err - } - - return v.client.ProcessTransaction(tx) -} - -// SetMigrationPermissions sets the permissions of another registry to allow migrations between the two. -func (v *LegacyEthereumKeeperRegistry) SetMigrationPermissions(peerAddress common.Address, permission uint8) error { - if v.version != ethereum.RegistryVersion_1_2 { - return fmt.Errorf("migration of upkeeps is only available for version 1.2 of the registries") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_2.SetPeerRegistryMigrationPermission(txOpts, peerAddress, permission) - if err != nil { - return err - } - - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumKeeperRegistry) SetRegistrar(registrarAddr string) error { - if v.version == ethereum.RegistryVersion_2_0 { - // we short circuit and exit, so we don't create a new txs messing up the nonce before exiting - return fmt.Errorf("please use set config") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - callOpts := bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: nil, - } - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err := v.registry1_1.SetRegistrar(txOpts, common.HexToAddress(registrarAddr)) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - tx, err := v.registry1_2.SetConfig(txOpts, newConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - tx, err := v.registry1_3.SetConfig(txOpts, newConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("keeper registry version %d is not supported", v.version) - } -} - -// AddUpkeepFunds adds link for particular upkeep id -func (v *LegacyEthereumKeeperRegistry) AddUpkeepFundsFromKey(_ *big.Int, _ *big.Int, _ int) error { - panic("this method is only supported by contracts using Seth client") -} - -// AddUpkeepFunds adds link for particular upkeep id -func (v *LegacyEthereumKeeperRegistry) AddUpkeepFunds(id *big.Int, amount *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.AddFunds(opts, id, amount) - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// GetUpkeepInfo gets upkeep info -func (v *LegacyEthereumKeeperRegistry) GetUpkeepInfo(ctx context.Context, id *big.Int) (*UpkeepInfo, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - uk, err := v.registry1_1.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_1_2: - uk, err := v.registry1_2.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_1_3: - uk, err := v.registry1_3.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_2_0: - uk, err := v.registry2_0.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil - case ethereum.RegistryVersion_2_1: - uk, err := v.registry2_1.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.PerformGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformedBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil - case ethereum.RegistryVersion_2_2: - return v.getUpkeepInfo22(opts, id) - } - - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -func (v *LegacyEthereumKeeperRegistry) getUpkeepInfo22(opts *bind.CallOpts, id *big.Int) (*UpkeepInfo, error) { - uk, err := v.registry2_2.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.PerformGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformedBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil -} - -func (v *LegacyEthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr string) (*KeeperInfo, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - var info struct { - Payee common.Address - Active bool - Balance *big.Int - } - var err error - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - info, err = v.registry1_1.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_1_2: - info, err = v.registry1_2.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_1_3: - info, err = v.registry1_3.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_2_0, ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - // this is not used anywhere - return nil, fmt.Errorf("not supported") - } - - if err != nil { - return nil, err - } - return &KeeperInfo{ - Payee: info.Payee.Hex(), - Active: info.Active, - Balance: info.Balance, - }, nil -} - -func (v *LegacyEthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, ocrConfig OCRv2Config) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - keepersAddresses := make([]common.Address, 0) - for _, k := range keepers { - keepersAddresses = append(keepersAddresses, common.HexToAddress(k)) - } - payeesAddresses := make([]common.Address, 0) - for _, p := range payees { - payeesAddresses = append(payeesAddresses, common.HexToAddress(p)) - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.SetConfig(opts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("not supported") - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// RegisterUpkeep registers contract to perform upkeep -func (v *LegacyEthereumKeeperRegistry) RegisterUpkeep(target string, gasLimit uint32, admin string, checkData []byte) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - nil, //offchain config - ) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("not supported") - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// CancelUpkeep cancels the given upkeep ID -func (v *LegacyEthereumKeeperRegistry) CancelUpkeep(id *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.CancelUpkeep(opts, id) - if err != nil { - return err - } - } - - v.l.Info(). - Str("Upkeep ID", strconv.FormatInt(id.Int64(), 10)). - Str("From", v.client.GetDefaultWallet().Address()). - Str("TX Hash", tx.Hash().String()). - Msg("Cancel Upkeep tx") - return v.client.ProcessTransaction(tx) -} - -// SetUpkeepGasLimit sets the perform gas limit for a given upkeep ID -func (v *LegacyEthereumKeeperRegistry) SetUpkeepGasLimit(id *big.Int, gas uint32) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - default: - return fmt.Errorf("keeper registry version %d is not supported for SetUpkeepGasLimit", v.version) - } - return v.client.ProcessTransaction(tx) -} - -// GetKeeperList get list of all registered keeper addresses -func (v *LegacyEthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - var list []common.Address - var err error - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - list, err = v.registry1_1.GetKeeperList(opts) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers - case ethereum.RegistryVersion_2_0: - state, err := v.registry2_0.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Transmitters - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return nil, fmt.Errorf("not supported") - } - - if err != nil { - return []string{}, err - } - addrs := make([]string, 0) - for _, ca := range list { - addrs = append(addrs, ca.Hex()) - } - return addrs, nil -} - -// UpdateCheckData updates the check data of an upkeep -func (v *LegacyEthereumKeeperRegistry) UpdateCheckData(id *big.Int, newCheckData []byte) error { - - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.UpdateCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.UpdateCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("UpdateCheckData is not supported by keeper registry version %d", v.version) - } -} - -// SetUpkeepTriggerConfig updates the trigger config of an upkeep (only for version 2.1) -func (v *LegacyEthereumKeeperRegistry) SetUpkeepTriggerConfig(id *big.Int, triggerConfig []byte) error { - - switch v.version { - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepTriggerConfig(opts, id, triggerConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepTriggerConfig(opts, id, triggerConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepTriggerConfig is not supported by keeper registry version %d", v.version) - } -} - -// SetUpkeepPrivilegeConfig sets the privilege config of an upkeep (only for version 2.1) -func (v *LegacyEthereumKeeperRegistry) SetUpkeepPrivilegeConfig(id *big.Int, privilegeConfig []byte) error { - - switch v.version { - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepPrivilegeConfig is not supported by keeper registry version %d", v.version) - } -} - -// PauseUpkeep stops an upkeep from an upkeep -func (v *LegacyEthereumKeeperRegistry) PauseUpkeep(id *big.Int) error { - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("PauseUpkeep is not supported by keeper registry version %d", v.version) - } -} - -// UnpauseUpkeep get list of all registered keeper addresses -func (v *LegacyEthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("UnpauseUpkeep is not supported by keeper registry version %d", v.version) - } -} - -func (v *LegacyEthereumKeeperRegistry) SetUpkeepOffchainConfig(id *big.Int, offchainConfig []byte) error { - switch v.version { - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepOffchainConfig is not supported by keeper registry version %d", v.version) - } -} - -// Parses upkeep performed log -func (v *LegacyEthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*UpkeepPerformedLog, error) { - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - } - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// ParseStaleUpkeepReportLog Parses Stale upkeep report log -func (v *LegacyEthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*StaleUpkeepReportLog, error) { - //nolint:exhaustive - switch v.version { - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - } - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// Parses the upkeep ID from an 'UpkeepRegistered' log, returns error on any other log -func (v *LegacyEthereumKeeperRegistry) ParseUpkeepIdFromRegisteredLog(log *types.Log) (*big.Int, error) { - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - } - - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// KeeperConsumerRoundConfirmer is a header subscription that awaits for a round of upkeeps -type KeeperConsumerRoundConfirmer struct { - instance KeeperConsumer - upkeepsValue int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - l zerolog.Logger -} - -// NewKeeperConsumerRoundConfirmer provides a new instance of a KeeperConsumerRoundConfirmer -func NewKeeperConsumerRoundConfirmer( - contract KeeperConsumer, - counterValue int, - timeout time.Duration, - logger zerolog.Logger, -) *KeeperConsumerRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &KeeperConsumerRoundConfirmer{ - instance: contract, - upkeepsValue: counterValue, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *KeeperConsumerRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - upkeeps, err := o.instance.Counter(context.Background()) - if err != nil { - return err - } - l := o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps", upkeeps.Int64()). - Int("Required upkeeps", o.upkeepsValue) - if upkeeps.Int64() == int64(o.upkeepsValue) { - l.Msg("Upkeep completed") - o.doneChan <- struct{}{} - } else { - l.Msg("Waiting for upkeep round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *KeeperConsumerRoundConfirmer) Wait() error { - for { - select { - case <-o.doneChan: - o.cancel() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for upkeeps to confirm: %d", o.upkeepsValue) - } - } -} - -// KeeperConsumerPerformanceRoundConfirmer is a header subscription that awaits for a round of upkeeps -type KeeperConsumerPerformanceRoundConfirmer struct { - instance KeeperConsumerPerformance - doneChan chan bool - context context.Context - cancel context.CancelFunc - - lastBlockNum uint64 // Records the number of the last block that came in - blockCadence int64 // How many blocks before an upkeep should happen - blockRange int64 // How many blocks to watch upkeeps for - blocksSinceSubscription int64 // How many blocks have passed since subscribing - expectedUpkeepCount int64 // The count of upkeeps expected next iteration - blocksSinceSuccessfulUpkeep int64 // How many blocks have come in since the last successful upkeep - allMissedUpkeeps []int64 // Tracks the amount of blocks missed in each missed upkeep - totalSuccessfulUpkeeps int64 - - metricsReporter *testreporters.KeeperBlockTimeTestReporter // Testreporter to track results - complete bool - l zerolog.Logger -} - -// NewKeeperConsumerPerformanceRoundConfirmer provides a new instance of a KeeperConsumerPerformanceRoundConfirmer -// Used to track and log performance test results for keepers -func NewKeeperConsumerPerformanceRoundConfirmer( - contract KeeperConsumerPerformance, - expectedBlockCadence int64, // Expected to upkeep every 5/10/20 blocks, for example - blockRange int64, - metricsReporter *testreporters.KeeperBlockTimeTestReporter, - logger zerolog.Logger, -) *KeeperConsumerPerformanceRoundConfirmer { - ctx, cancelFunc := context.WithCancel(context.Background()) - return &KeeperConsumerPerformanceRoundConfirmer{ - instance: contract, - doneChan: make(chan bool), - context: ctx, - cancel: cancelFunc, - blockCadence: expectedBlockCadence, - blockRange: blockRange, - blocksSinceSubscription: 0, - blocksSinceSuccessfulUpkeep: 0, - expectedUpkeepCount: 1, - allMissedUpkeeps: []int64{}, - totalSuccessfulUpkeeps: 0, - metricsReporter: metricsReporter, - complete: false, - lastBlockNum: 0, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *KeeperConsumerPerformanceRoundConfirmer) ReceiveHeader(receivedHeader blockchain.NodeHeader) error { - if receivedHeader.Number.Uint64() <= o.lastBlockNum { // Uncle / reorg we won't count - return nil - } - o.lastBlockNum = receivedHeader.Number.Uint64() - // Increment block counters - o.blocksSinceSubscription++ - o.blocksSinceSuccessfulUpkeep++ - upkeepCount, err := o.instance.GetUpkeepCount(context.Background()) - if err != nil { - return err - } - - isEligible, err := o.instance.CheckEligible(context.Background()) - if err != nil { - return err - } - if isEligible { - o.l.Trace(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Msg("Upkeep Now Eligible") - } - if upkeepCount.Int64() >= o.expectedUpkeepCount { // Upkeep was successful - if o.blocksSinceSuccessfulUpkeep < o.blockCadence { // If there's an early upkeep, that's weird - o.l.Error(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Err(errors.New("found an early Upkeep")) - return fmt.Errorf("found an early Upkeep on contract %s", o.instance.Address()) - } else if o.blocksSinceSuccessfulUpkeep == o.blockCadence { // Perfectly timed upkeep - o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Msg("Successful Upkeep on Expected Cadence") - o.totalSuccessfulUpkeeps++ - } else { // Late upkeep - o.l.Warn(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Msg("Upkeep Completed Late") - o.allMissedUpkeeps = append(o.allMissedUpkeeps, o.blocksSinceSuccessfulUpkeep-o.blockCadence) - } - // Update upkeep tracking values - o.blocksSinceSuccessfulUpkeep = 0 - o.expectedUpkeepCount++ - } - - if o.blocksSinceSubscription > o.blockRange { - if o.blocksSinceSuccessfulUpkeep > o.blockCadence { - o.l.Warn(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Expected Upkeep Count", o.expectedUpkeepCount). - Int64("Blocks Waiting", o.blocksSinceSuccessfulUpkeep). - Int64("Total Blocks Watched", o.blocksSinceSubscription). - Msg("Finished Watching for Upkeeps While Waiting on a Late Upkeep") - o.allMissedUpkeeps = append(o.allMissedUpkeeps, o.blocksSinceSuccessfulUpkeep-o.blockCadence) - } else { - o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Total Blocks Watched", o.blocksSinceSubscription). - Msg("Finished Watching for Upkeeps") - } - o.doneChan <- true - o.complete = true - return nil - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *KeeperConsumerPerformanceRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - o.logDetails() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for expected upkeep count to confirm: %d", o.expectedUpkeepCount) - } - } -} - -func (o *KeeperConsumerPerformanceRoundConfirmer) Complete() bool { - return o.complete -} - -func (o *KeeperConsumerPerformanceRoundConfirmer) logDetails() { - report := testreporters.KeeperBlockTimeTestReport{ - ContractAddress: o.instance.Address(), - TotalExpectedUpkeeps: o.blockRange / o.blockCadence, - TotalSuccessfulUpkeeps: o.totalSuccessfulUpkeeps, - AllMissedUpkeeps: o.allMissedUpkeeps, - } - o.metricsReporter.ReportMutex.Lock() - o.metricsReporter.Reports = append(o.metricsReporter.Reports, report) - defer o.metricsReporter.ReportMutex.Unlock() -} - -// LegacyKeeperConsumerBenchmarkRoundConfirmer is a header subscription that awaits for a round of upkeeps -type LegacyKeeperConsumerBenchmarkRoundConfirmer struct { - instance AutomationConsumerBenchmark - registry KeeperRegistry - upkeepID *big.Int - doneChan chan bool - context context.Context - cancel context.CancelFunc - - firstBlockNum uint64 // Records the number of the first block that came in - lastBlockNum uint64 // Records the number of the last block that came in - blockRange int64 // How many blocks to watch upkeeps for - upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' - metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results - upkeepIndex int64 - firstEligibleBuffer int64 - - // State variables, changes as we get blocks - blocksSinceSubscription int64 // How many blocks have passed since subscribing - blocksSinceEligible int64 // How many blocks have come in since upkeep has been eligible for check - countEligible int64 // Number of times the upkeep became eligible - countMissed int64 // Number of times we missed SLA for performing upkeep - upkeepCount int64 // The count of upkeeps done so far - allCheckDelays []int64 // Tracks the amount of blocks missed before an upkeep since it became eligible - complete bool - l zerolog.Logger -} - -// NewLegacyKeeperConsumerBenchmarkRoundConfirmer provides a new instance of a LegacyKeeperConsumerBenchmarkRoundConfirmer -// Used to track and log benchmark test results for keepers -func NewLegacyKeeperConsumerBenchmarkRoundConfirmer( - contract AutomationConsumerBenchmark, - registry KeeperRegistry, - upkeepID *big.Int, - blockRange int64, - upkeepSLA int64, - metricsReporter *testreporters.KeeperBenchmarkTestReporter, - upkeepIndex int64, - firstEligibleBuffer int64, - logger zerolog.Logger, -) *LegacyKeeperConsumerBenchmarkRoundConfirmer { - ctx, cancelFunc := context.WithCancel(context.Background()) - return &LegacyKeeperConsumerBenchmarkRoundConfirmer{ - instance: contract, - registry: registry, - upkeepID: upkeepID, - doneChan: make(chan bool), - context: ctx, - cancel: cancelFunc, - blockRange: blockRange, - upkeepSLA: upkeepSLA, - blocksSinceSubscription: 0, - blocksSinceEligible: 0, - upkeepCount: 0, - allCheckDelays: []int64{}, - metricsReporter: metricsReporter, - complete: false, - lastBlockNum: 0, - upkeepIndex: upkeepIndex, - firstBlockNum: 0, - firstEligibleBuffer: firstEligibleBuffer, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) ReceiveHeader(receivedHeader blockchain.NodeHeader) error { - if receivedHeader.Number.Uint64() <= o.lastBlockNum { // Uncle / reorg we won't count - return nil - } - if o.firstBlockNum == 0 { - o.firstBlockNum = receivedHeader.Number.Uint64() - } - o.lastBlockNum = receivedHeader.Number.Uint64() - // Increment block counters - o.blocksSinceSubscription++ - - upkeepCount, err := o.instance.GetUpkeepCount(context.Background(), big.NewInt(o.upkeepIndex)) - if err != nil { - return err - } - - if upkeepCount.Int64() > o.upkeepCount { // A new upkeep was done - if upkeepCount.Int64() != o.upkeepCount+1 { - return errors.New("upkeep count increased by more than 1 in a single block") - } - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeep_Count", upkeepCount.Int64()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Performed") - - if o.blocksSinceEligible > o.upkeepSLA { - o.l.Warn(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Missed SLA") - o.countMissed++ - } - - o.allCheckDelays = append(o.allCheckDelays, o.blocksSinceEligible) - o.upkeepCount++ - o.blocksSinceEligible = 0 - } - - isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleBuffer)) - if err != nil { - return err - } - if isEligible { - if o.blocksSinceEligible == 0 { - // First time this upkeep became eligible - o.countEligible++ - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Now Eligible") - } - o.blocksSinceEligible++ - } - - if o.blocksSinceSubscription >= o.blockRange || int64(o.lastBlockNum-o.firstBlockNum) >= o.blockRange { - if o.blocksSinceEligible > 0 { - if o.blocksSinceEligible > o.upkeepSLA { - o.l.Warn(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep remained eligible at end of test and missed SLA") - o.countMissed++ - } else { - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeep_Count", upkeepCount.Int64()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep remained eligible at end of test and was within SLA") - } - o.allCheckDelays = append(o.allCheckDelays, o.blocksSinceEligible) - } - - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeeps_Performed", upkeepCount.Int64()). - Int64("Total_Blocks_Watched", o.blocksSinceSubscription). - Str("Registry_Address", o.registry.Address()). - Msg("Finished Watching for Upkeeps") - - o.doneChan <- true - o.complete = true - return nil - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - o.logDetails() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for expected number of blocks: %d", o.blockRange) - } - } -} - -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) Complete() bool { - return o.complete -} - -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) logDetails() { - report := testreporters.KeeperBenchmarkTestReport{ - ContractAddress: o.instance.Address(), - TotalEligibleCount: o.countEligible, - TotalSLAMissedUpkeeps: o.countMissed, - TotalPerformedUpkeeps: o.upkeepCount, - AllCheckDelays: o.allCheckDelays, - RegistryAddress: o.registry.Address(), - } - o.metricsReporter.ReportMutex.Lock() - o.metricsReporter.Reports = append(o.metricsReporter.Reports, report) - defer o.metricsReporter.ReportMutex.Unlock() -} - -// LegacyEthereumUpkeepCounter represents keeper consumer (upkeep) counter contract -type LegacyEthereumUpkeepCounter struct { - client blockchain.EVMClient - consumer *upkeep_counter_wrapper.UpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumUpkeepCounter) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumUpkeepCounter) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} -func (v *LegacyEthereumUpkeepCounter) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -func (v *LegacyEthereumUpkeepCounter) SetSpread(testRange *big.Int, interval *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetSpread(opts, testRange, interval) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// Just pass for non-logtrigger -func (v *LegacyEthereumUpkeepCounter) Start() error { - return nil -} - -// LegacyEthereumUpkeepPerformCounterRestrictive represents keeper consumer (upkeep) counter contract -type LegacyEthereumUpkeepPerformCounterRestrictive struct { - client blockchain.EVMClient - consumer *upkeep_perform_counter_restrictive_wrapper.UpkeepPerformCounterRestrictive - address *common.Address -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - count, err := v.consumer.GetCountPerforms(opts) - return count, err -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) SetSpread(testRange *big.Int, interval *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetSpread(opts, testRange, interval) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// EthereumKeeperConsumer represents keeper consumer (upkeep) contract -type EthereumKeeperConsumer struct { - client blockchain.EVMClient - consumer *keeper_consumer_wrapper.KeeperConsumer - address *common.Address -} - -// Just pass for non-logtrigger -func (v *EthereumKeeperConsumer) Start() error { - return nil -} - -func (v *EthereumKeeperConsumer) Address() string { - return v.address.Hex() -} - -func (v *EthereumKeeperConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationStreamsLookupUpkeepConsumer struct { - client blockchain.EVMClient - consumer *streams_lookup_upkeep_wrapper.StreamsLookupUpkeep - address *common.Address -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Start() error { - // For this consumer upkeep, we use this Start() function to set ParamKeys so as to run mercury v0.2 - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - // The default values of ParamKeys are "feedIDs" and "timestamp" which are for v0.3 - tx, err := v.consumer.SetParamKeys(txOpts, "feedIdHex", "blockNumber") - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer struct { - client blockchain.EVMClient - consumer *log_triggered_streams_lookup_wrapper.LogTriggeredStreamsLookup - address *common.Address -} - -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Address() string { - return v.address.Hex() -} - -// Kick off the log trigger event. The contract uses Mercury v0.2 so no need to set ParamKeys -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Start() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.consumer.Start(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationLogCounterConsumer struct { - client blockchain.EVMClient - consumer *log_upkeep_counter_wrapper.LogUpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Start() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.consumer.Start(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationSimpleLogCounterConsumer struct { - client blockchain.EVMClient - consumer *simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Start() error { - return nil -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -// LegacyEthereumKeeperConsumerPerformance represents a more complicated keeper consumer contract, one intended only for -// performance tests. -type LegacyEthereumKeeperConsumerPerformance struct { - client blockchain.EVMClient - consumer *keeper_consumer_performance_wrapper.KeeperConsumerPerformance - address *common.Address -} - -func (v *LegacyEthereumKeeperConsumerPerformance) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperConsumerPerformance) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -func (v *LegacyEthereumKeeperConsumerPerformance) CheckEligible(ctx context.Context) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.CheckEligible(opts) - return eligible, err -} - -func (v *LegacyEthereumKeeperConsumerPerformance) GetUpkeepCount(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.GetCountPerforms(opts) - return eligible, err -} - -func (v *LegacyEthereumKeeperConsumerPerformance) SetCheckGasToBurn(_ context.Context, gas *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetCheckGasToBurn(opts, gas) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumKeeperConsumerPerformance) SetPerformGasToBurn(_ context.Context, gas *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetPerformGasToBurn(opts, gas) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// LegacyEthereumKeeperPerformDataCheckerConsumer represents keeper perform data checker contract -type LegacyEthereumKeeperPerformDataCheckerConsumer struct { - client blockchain.EVMClient - performDataChecker *perform_data_checker_wrapper.PerformDataChecker - address *common.Address -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.performDataChecker.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) SetExpectedData(_ context.Context, expectedData []byte) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.performDataChecker.SetExpectedData(opts, expectedData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// LegacyEthereumAutomationConsumerBenchmark represents a more complicated keeper consumer contract, one intended only for -// Benchmark tests. -type LegacyEthereumAutomationConsumerBenchmark struct { - client blockchain.EVMClient - consumer *automation_consumer_benchmark.AutomationConsumerBenchmark - address *common.Address -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) CheckEligible(ctx context.Context, id *big.Int, _range *big.Int, firstEligibleBuffer *big.Int) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.CheckEligible(opts, id, _range, firstEligibleBuffer) - return eligible, err -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) GetUpkeepCount(ctx context.Context, id *big.Int) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.GetCountPerforms(opts, id) - return eligible, err -} - -// LegacyEthereumKeeperRegistrar corresponds to the registrar which is used to send requests to the registry when -// registering new upkeeps. -type LegacyEthereumKeeperRegistrar struct { - client blockchain.EVMClient - registrar *keeper_registrar_wrapper1_2.KeeperRegistrar - registrar20 *keeper_registrar_wrapper2_0.KeeperRegistrar - registrar21 *registrar21.AutomationRegistrar - address *common.Address -} - -func (v *LegacyEthereumKeeperRegistrar) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperRegistrar) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -// EncodeRegisterRequest encodes register request to call it through link token TransferAndCall -func (v *LegacyEthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool) ([]byte, error) { - if v.registrar20 != nil { - registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.ABI)) - if err != nil { - return nil, err - } - req, err := registryABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - checkData, - []byte{}, //offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - - if err != nil { - return nil, err - } - return req, nil - } else if v.registrar21 != nil { - if isLogTrigger { - var topic0InBytes [32]byte - // bytes representation of 0x0000000000000000000000000000000000000000000000000000000000000000 - bytes0 := [32]byte{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - } - if isMercury { - // bytes representation of 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd - topic0InBytes = [32]byte{209, 255, 233, 228, 85, 129, 193, 29, 125, 159, 46, 213, 247, 82, 23, 205, 75, 233, 248, 183, 238, 230, 175, 15, 109, 3, 244, 109, 229, 57, 86, 205} - } else { - // bytes representation of 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d - topic0InBytes = [32]byte{ - 61, 83, 163, 149, 80, 224, 70, 136, - 6, 88, 39, 243, 187, 134, 88, 76, - 176, 7, 171, 158, 188, 167, 235, - 213, 40, 231, 48, 28, 156, 49, 235, 93, - } - } - - logTriggerConfigStruct := ac.IAutomationV21PlusCommonLogTriggerConfig{ - ContractAddress: common.HexToAddress(upkeepAddr), - FilterSelector: 0, - Topic0: topic0InBytes, - Topic1: bytes0, - Topic2: bytes0, - Topic3: bytes0, - } - encodedLogTriggerConfig, err := compatibleUtils.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct) - if err != nil { - return nil, err - } - - req, err := registrarABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - uint8(1), // trigger type - checkData, - encodedLogTriggerConfig, // triggerConfig - []byte{}, // offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - - return req, err - } - req, err := registrarABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - uint8(0), // trigger type - checkData, - []byte{}, // triggerConfig - []byte{}, // offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - return req, err - } - registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.ABI)) - if err != nil { - return nil, err - } - req, err := registryABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - checkData, - amount, - source, - common.HexToAddress(senderAddr), - ) - if err != nil { - return nil, err - } - return req, nil +// KeeperRegistrarSettings represents settings for registrar contract +type KeeperRegistrarSettings struct { + AutoApproveConfigType uint8 + AutoApproveMaxAllowed uint16 + RegistryAddr string + MinLinkJuels *big.Int } -// LegacyEthereumUpkeepTranscoder represents the transcoder which is used to perform migrations -// of upkeeps from one registry to another. -type LegacyEthereumUpkeepTranscoder struct { - client blockchain.EVMClient - transcoder *upkeep_transcoder.UpkeepTranscoder - address *common.Address +// KeeperInfo keeper status and balance info +type KeeperInfo struct { + Payee string + Active bool + Balance *big.Int } -func (v *LegacyEthereumUpkeepTranscoder) Address() string { - return v.address.Hex() +// UpkeepInfo keeper target info +type UpkeepInfo struct { + Target string + ExecuteGas uint32 + CheckData []byte + Balance *big.Int + LastKeeper string + Admin string + MaxValidBlocknumber uint64 + LastPerformBlockNumber uint32 + AmountSpent *big.Int + Paused bool + OffchainConfig []byte } diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index 7b79ca01739..d4757fa869c 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -6,6 +6,9 @@ import ( "math/big" "time" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog/log" @@ -394,7 +397,7 @@ func (v *EthereumVRFConsumer) Address() string { } func (v *EthereumVRFConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // RequestRandomness requests VRF randomness @@ -421,7 +424,7 @@ func (v *EthereumVRFConsumer) RandomnessOutput(ctx context.Context) (*big.Int, e // Fund sends specified currencies to the contract func (v *EthereumVRF) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // ProofLength returns the PROOFLENGTH call from the VRF contract @@ -431,3 +434,66 @@ func (v *EthereumVRF) ProofLength(ctx context.Context) (*big.Int, error) { Context: ctx, }) } + +func LoadVRFCoordinatorV2_5(seth *seth.Client, addr string) (VRFCoordinatorV2_5, error) { + address := common.HexToAddress(addr) + abi, err := vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.GetAbi() + if err != nil { + return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to get VRFCoordinatorV2_5 ABI: %w", err) + } + seth.ContractStore.AddABI("VRFCoordinatorV2_5", *abi) + seth.ContractStore.AddBIN("VRFCoordinatorV2_5", common.FromHex(vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.Bin)) + + contract, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to instantiate VRFCoordinatorV2_5 instance: %w", err) + } + + return &EthereumVRFCoordinatorV2_5{ + client: seth, + address: address, + coordinator: contract, + }, nil +} + +func LoadBlockHashStore(seth *seth.Client, addr string) (BlockHashStore, error) { + address := common.HexToAddress(addr) + abi, err := blockhash_store.BlockhashStoreMetaData.GetAbi() + if err != nil { + return &EthereumBlockhashStore{}, fmt.Errorf("failed to get BlockHashStore ABI: %w", err) + } + seth.ContractStore.AddABI("BlockHashStore", *abi) + seth.ContractStore.AddBIN("BlockHashStore", common.FromHex(blockhash_store.BlockhashStoreMetaData.Bin)) + + contract, err := blockhash_store.NewBlockhashStore(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumBlockhashStore{}, fmt.Errorf("failed to instantiate BlockHashStore instance: %w", err) + } + + return &EthereumBlockhashStore{ + client: seth, + address: &address, + blockHashStore: contract, + }, nil +} + +func LoadVRFv2PlusLoadTestConsumer(seth *seth.Client, addr string) (VRFv2PlusLoadTestConsumer, error) { + address := common.HexToAddress(addr) + abi, err := vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.GetAbi() + if err != nil { + return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to get VRFV2PlusLoadTestWithMetrics ABI: %w", err) + } + seth.ContractStore.AddABI("VRFV2PlusLoadTestWithMetrics", *abi) + seth.ContractStore.AddBIN("VRFV2PlusLoadTestWithMetrics", common.FromHex(vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.Bin)) + + contract, err := vrf_v2plus_load_test_with_metrics.NewVRFV2PlusLoadTestWithMetrics(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to instantiate VRFV2PlusLoadTestWithMetrics instance: %w", err) + } + + return &EthereumVRFv2PlusLoadTestConsumer{ + client: seth, + address: address, + consumer: contract, + }, nil +} diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index be588ea3e3a..a9d1a93769d 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -804,7 +804,7 @@ func (v *EthereumVRFConsumerV2) GasAvailable() (*big.Int, error) { } func (v *EthereumVRFConsumerV2) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // RequestRandomness request VRFv2 random words @@ -1028,7 +1028,7 @@ func (v *EthereumVRFV2WrapperLoadTestConsumer) Address() string { } func (v *EthereumVRFV2WrapperLoadTestConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } func (v *EthereumVRFV2WrapperLoadTestConsumer) RequestRandomness(coordinator Coordinator, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*CoordinatorRandomWordsRequested, error) { diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 882baafcd19..9f6f6665d21 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -1121,7 +1121,7 @@ func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Address() string { } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomness( diff --git a/integration-tests/contracts/multicall.go b/integration-tests/contracts/multicall.go index be1af13cceb..6b73aed084c 100644 --- a/integration-tests/contracts/multicall.go +++ b/integration-tests/contracts/multicall.go @@ -1,8 +1,6 @@ package contracts import ( - "context" - "fmt" "math/big" "strings" @@ -10,11 +8,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog/log" "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" ) @@ -41,19 +36,6 @@ type Result struct { ReturnData []byte } -func WaitForSuccessfulTxMined(evmClient blockchain.EVMClient, tx *types.Transaction) error { - log.Debug().Str("tx", tx.Hash().Hex()).Msg("waiting for tx to be mined") - receipt, err := bind.WaitMined(context.Background(), evmClient.DeployBackend(), tx) - if err != nil { - return err - } - if receipt.Status != types.ReceiptStatusSuccessful { - return fmt.Errorf("tx failed %s", tx.Hash().Hex()) - } - log.Debug().Str("tx", tx.Hash().Hex()).Str("Network", evmClient.GetNetworkName()).Msg("tx mined successfully") - return nil -} - func MultiCallLogTriggerLoadGen( client *seth.Client, multiCallAddress string, diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index 25b87bcc5ba..85e76054c71 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -1,105 +1,123 @@ package contracts import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" + "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" ) -type LegacyLogEmitterContract struct { +type LogEmitterContract struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *le.LogEmitter l zerolog.Logger } -func (e *LegacyLogEmitterContract) Address() common.Address { +func (e *LogEmitterContract) Address() common.Address { return e.address } -func (e *LegacyLogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } +func (e *LogEmitterContract) EmitLogIntsFromKey(ints []int, keyNum int) (*types.Transaction, error) { bigInts := make([]*big.Int, len(ints)) for i, v := range ints { bigInts[i] = big.NewInt(int64(v)) } - tx, err := e.instance.EmitLog1(opts, bigInts) + tx, err := e.client.Decode(e.instance.EmitLog1(e.client.NewTXKeyOpts(keyNum), bigInts)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } +func (e *LogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { + return e.EmitLogIntsFromKey(ints, 0) +} + +func (e *LogEmitterContract) EmitLogIntsIndexedFromKey(ints []int, keyNum int) (*types.Transaction, error) { bigInts := make([]*big.Int, len(ints)) for i, v := range ints { bigInts[i] = big.NewInt(int64(v)) } - tx, err := e.instance.EmitLog2(opts, bigInts) + tx, err := e.client.Decode(e.instance.EmitLog2(e.client.NewTXKeyOpts(keyNum), bigInts)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.EmitLog4(opts, big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count))) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { + return e.EmitLogIntsIndexedFromKey(ints, 0) } -func (e *LegacyLogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func (e *LogEmitterContract) EmitLogIntMultiIndexedFromKey(ints int, ints2 int, count int, keyNum int) (*types.Transaction, error) { + tx, err := e.client.Decode(e.instance.EmitLog4(e.client.NewTXKeyOpts(keyNum), big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count)))) if err != nil { return nil, err } - tx, err := e.instance.EmitLog3(opts, strings) + + return tx.Transaction, nil +} + +func (e *LogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { + return e.EmitLogIntMultiIndexedFromKey(ints, ints2, count, 0) +} + +func (e *LogEmitterContract) EmitLogStringsFromKey(strings []string, keyNum int) (*types.Transaction, error) { + tx, err := e.client.Decode(e.instance.EmitLog3(e.client.NewTXKeyOpts(keyNum), strings)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { + return e.EmitLogStringsFromKey(strings, 0) +} + +func (e *LogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { return e.EmitLogInts([]int{payload}) } -func (e *LegacyLogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { return e.EmitLogIntsIndexed([]int{payload}) } -func (e *LegacyLogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { return e.EmitLogStrings([]string{strings}) } -func (e *LegacyLogEmitterContract) EmitLogIntsFromKey(_ []int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") -} -func (e *LegacyLogEmitterContract) EmitLogIntsIndexedFromKey(_ []int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") +func DeployLogEmitterContract(l zerolog.Logger, client *seth.Client) (LogEmitter, error) { + return DeployLogEmitterContractFromKey(l, client, 0) } -func (e *LegacyLogEmitterContract) EmitLogIntMultiIndexedFromKey(_ int, _ int, _ int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") -} -func (e *LegacyLogEmitterContract) EmitLogStringsFromKey(_ []string, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") + +func DeployLogEmitterContractFromKey(l zerolog.Logger, client *seth.Client, keyNum int) (LogEmitter, error) { + abi, err := le.LogEmitterMetaData.GetAbi() + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("failed to get LogEmitter ABI: %w", err) + } + data, err := client.DeployContract(client.NewTXKeyOpts(keyNum), "LogEmitter", *abi, common.FromHex(le.LogEmitterMetaData.Bin)) + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("LogEmitter instance deployment have failed: %w", err) + } + + instance, err := le.NewLogEmitter(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("failed to instantiate LogEmitter instance: %w", err) + } + + return &LogEmitterContract{ + client: client, + instance: instance, + address: data.Address, + l: l, + }, err } diff --git a/integration-tests/contracts/test_contracts_seth.go b/integration-tests/contracts/test_contracts_seth.go deleted file mode 100644 index 85e76054c71..00000000000 --- a/integration-tests/contracts/test_contracts_seth.go +++ /dev/null @@ -1,123 +0,0 @@ -package contracts - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" -) - -type LogEmitterContract struct { - address common.Address - client *seth.Client - instance *le.LogEmitter - l zerolog.Logger -} - -func (e *LogEmitterContract) Address() common.Address { - return e.address -} - -func (e *LogEmitterContract) EmitLogIntsFromKey(ints []int, keyNum int) (*types.Transaction, error) { - bigInts := make([]*big.Int, len(ints)) - for i, v := range ints { - bigInts[i] = big.NewInt(int64(v)) - } - tx, err := e.client.Decode(e.instance.EmitLog1(e.client.NewTXKeyOpts(keyNum), bigInts)) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { - return e.EmitLogIntsFromKey(ints, 0) -} - -func (e *LogEmitterContract) EmitLogIntsIndexedFromKey(ints []int, keyNum int) (*types.Transaction, error) { - bigInts := make([]*big.Int, len(ints)) - for i, v := range ints { - bigInts[i] = big.NewInt(int64(v)) - } - tx, err := e.client.Decode(e.instance.EmitLog2(e.client.NewTXKeyOpts(keyNum), bigInts)) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { - return e.EmitLogIntsIndexedFromKey(ints, 0) -} - -func (e *LogEmitterContract) EmitLogIntMultiIndexedFromKey(ints int, ints2 int, count int, keyNum int) (*types.Transaction, error) { - tx, err := e.client.Decode(e.instance.EmitLog4(e.client.NewTXKeyOpts(keyNum), big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count)))) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { - return e.EmitLogIntMultiIndexedFromKey(ints, ints2, count, 0) -} - -func (e *LogEmitterContract) EmitLogStringsFromKey(strings []string, keyNum int) (*types.Transaction, error) { - tx, err := e.client.Decode(e.instance.EmitLog3(e.client.NewTXKeyOpts(keyNum), strings)) - if err != nil { - return nil, err - } - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { - return e.EmitLogStringsFromKey(strings, 0) -} - -func (e *LogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { - return e.EmitLogInts([]int{payload}) -} - -func (e *LogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { - return e.EmitLogIntsIndexed([]int{payload}) -} - -func (e *LogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { - return e.EmitLogStrings([]string{strings}) -} - -func DeployLogEmitterContract(l zerolog.Logger, client *seth.Client) (LogEmitter, error) { - return DeployLogEmitterContractFromKey(l, client, 0) -} - -func DeployLogEmitterContractFromKey(l zerolog.Logger, client *seth.Client, keyNum int) (LogEmitter, error) { - abi, err := le.LogEmitterMetaData.GetAbi() - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("failed to get LogEmitter ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXKeyOpts(keyNum), "LogEmitter", *abi, common.FromHex(le.LogEmitterMetaData.Bin)) - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("LogEmitter instance deployment have failed: %w", err) - } - - instance, err := le.NewLogEmitter(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("failed to instantiate LogEmitter instance: %w", err) - } - - return &LogEmitterContract{ - client: client, - instance: instance, - address: data.Address, - l: l, - }, err -} diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 73e22c58ab3..6007e03406b 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "maps" - "math/big" "net/url" "os" "regexp" @@ -13,7 +12,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/pelletier/go-toml/v2" @@ -23,7 +21,6 @@ import ( tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" @@ -271,25 +268,6 @@ func (n *ClNode) ChainlinkNodeAddress() (common.Address, error) { return common.HexToAddress(addr), nil } -func (n *ClNode) Fund(evmClient blockchain.EVMClient, amount *big.Float) error { - toAddress, err := n.API.PrimaryEthAddress() - if err != nil { - return err - } - n.l.Debug(). - Str("ChainId", evmClient.GetChainID().String()). - Str("Address", toAddress). - Msg("Funding Chainlink Node") - toAddr := common.HexToAddress(toAddress) - gasEstimates, err := evmClient.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - return evmClient.Fund(toAddress, amount, gasEstimates) -} - func (n *ClNode) containerStartOrRestart(restartDb bool) error { var err error if restartDb { diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index c25cac12e67..fb72025a05a 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -2,19 +2,15 @@ package test_env import ( "context" - "encoding/json" "fmt" - "math/big" "os" "path/filepath" "runtime" "strings" "testing" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" tc "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" @@ -23,13 +19,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/runid" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" d "github.com/smartcontractkit/chainlink/integration-tests/docker" ) @@ -46,10 +38,6 @@ type CLClusterTestEnv struct { /* components */ ClCluster *ClCluster MockAdapter *test_env.Killgrave - evmClients map[int64]blockchain.EVMClient - sethClients map[int64]*seth.Client - ContractDeployer contracts.ContractDeployer - ContractLoader contracts.ContractLoader PrivateEthereumConfigs []*ctf_config.EthereumNetworkConfig EVMNetworks []*blockchain.EVMNetwork rpcProviders map[int64]*test_env.RpcProvider @@ -90,12 +78,6 @@ func (te *CLClusterTestEnv) WithTestInstance(t *testing.T) *CLClusterTestEnv { return te } -func (te *CLClusterTestEnv) ParallelTransactions(enabled bool) { - for _, evmClient := range te.evmClients { - evmClient.ParallelTransactions(enabled) - } -} - func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetworkConfig) (blockchain.EVMNetwork, test_env.RpcProvider, error) { // if environment is being restored from a previous state, use the existing config // this might fail terribly if temporary folders with chain data on the host machine were removed @@ -165,41 +147,6 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i return te.ClCluster.Start() } -// FundChainlinkNodes will fund all the provided Chainlink nodes with a set amount of native currency -func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error { - if len(te.sethClients) == 0 && len(te.evmClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to fund chainlink nodes") - } - - if len(te.sethClients) > 0 && len(te.evmClients) > 0 { - return fmt.Errorf("both EVMClients and SethClient are set, you can't use both at the same time") - } - - if len(te.sethClients) > 0 { - for _, sethClient := range te.sethClients { - if err := actions_seth.FundChainlinkNodesFromRootAddress(te.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(te.ClCluster.NodeAPIs()), amount); err != nil { - return err - } - } - } - - if len(te.evmClients) > 0 { - for _, evmClient := range te.evmClients { - for _, cl := range te.ClCluster.Nodes { - if err := cl.Fund(evmClient, amount); err != nil { - return fmt.Errorf("%s, err: %w", ErrFundCLNode, err) - } - } - err := evmClient.WaitForEvents() - if err != nil { - return err - } - } - } - - return nil -} - func (te *CLClusterTestEnv) Terminate() error { // TESTCONTAINERS_RYUK_DISABLED=false by default so ryuk will remove all // the containers and the Network @@ -229,32 +176,11 @@ func (te *CLClusterTestEnv) Cleanup(opts CleanupOpts) error { te.logWhetherAllContainersAreRunning() - if len(te.evmClients) == 0 && len(te.sethClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to return funds from chainlink nodes during cleanup") - } else if te.isSimulatedNetwork { - te.l.Info(). - Msg("Network is a simulated network. Skipping fund return.") - } else { - if err := te.returnFunds(); err != nil { - return err - } - } - err := te.handleNodeCoverageReports(opts.TestName) if err != nil { te.l.Error().Err(err).Msg("Error handling node coverage reports") } - // close EVMClient connections - for _, evmClient := range te.evmClients { - err := evmClient.Close() - return err - } - - for _, sethClient := range te.sethClients { - sethClient.Client.Close() - } - return nil } @@ -357,85 +283,28 @@ func (te *CLClusterTestEnv) logWhetherAllContainersAreRunning() { } } -func (te *CLClusterTestEnv) returnFunds() error { - te.l.Info().Msg("Attempting to return Chainlink node funds to default network wallets") - - if len(te.evmClients) == 0 && len(te.sethClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to return funds from chainlink nodes") - } - - for _, evmClient := range te.evmClients { - for _, chainlinkNode := range te.ClCluster.Nodes { - fundedKeys, err := chainlinkNode.API.ExportEVMKeysForChain(evmClient.GetChainID().String()) - if err != nil { - return err - } - for _, key := range fundedKeys { - keyToDecrypt, err := json.Marshal(key) - if err != nil { - return err - } - // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM - // issues. So we avoid running in parallel; slower, but safer. - decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) - if err != nil { - return err - } - if te.evmClients[0] != nil { - te.l.Debug(). - Str("ChainId", evmClient.GetChainID().String()). - Msg("Returning funds from chainlink node") - if err = evmClient.ReturnFunds(decryptedKey.PrivateKey); err != nil { - // If we fail to return funds from one, go on to try the others anyway - te.l.Error().Err(err).Str("Node", chainlinkNode.ContainerName).Msg("Error returning funds from node") - } - } - } - } - } - - for _, sethClient := range te.sethClients { - if err := actions_seth.ReturnFundsFromNodes(te.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(te.ClCluster.NodeAPIs())); err != nil { - te.l.Error().Err(err).Msg("Error returning funds from node") - } - } - - te.l.Info().Msg("Returned funds from Chainlink nodes") - return nil -} - -func (te *CLClusterTestEnv) GetEVMClient(chainId int64) (blockchain.EVMClient, error) { - if len(te.sethClients) > 0 { - return nil, fmt.Errorf("Environment is using Seth clients, not EVM clients") - } - - if evmClient, ok := te.evmClients[chainId]; ok { - return evmClient, nil +func (te *CLClusterTestEnv) GetRpcProvider(chainId int64) (*test_env.RpcProvider, error) { + if rpc, ok := te.rpcProviders[chainId]; ok { + return rpc, nil } - return nil, fmt.Errorf("no EVMClient available for chain ID %d", chainId) + return nil, fmt.Errorf("no RPC provider available for chain ID %d", chainId) } -func (te *CLClusterTestEnv) GetSethClient(chainId int64) (*seth.Client, error) { - if len(te.evmClients) > 0 { - return nil, fmt.Errorf("Environment is using EVMClients, not Seth clients") - } - if sethClient, ok := te.sethClients[chainId]; ok { - return sethClient, nil +func (te *CLClusterTestEnv) GetFirstEvmNetwork() (*blockchain.EVMNetwork, error) { + if len(te.EVMNetworks) == 0 { + return nil, fmt.Errorf("no EVM networks available") } - return nil, fmt.Errorf("no Seth client available for chain ID %d", chainId) + return te.EVMNetworks[0], nil } -func (te *CLClusterTestEnv) GetSethClientForSelectedNetwork() (*seth.Client, error) { - n := networks.MustGetSelectedNetworkConfig(te.TestConfig.GetNetworkConfig())[0] - return te.GetSethClient(n.ChainID) -} - -func (te *CLClusterTestEnv) GetRpcProvider(chainId int64) (*test_env.RpcProvider, error) { - if rpc, ok := te.rpcProviders[chainId]; ok { - return rpc, nil +func (te *CLClusterTestEnv) GetEVMNetworkForChainId(chainId int64) (*blockchain.EVMNetwork, error) { + for _, network := range te.EVMNetworks { + if network.ChainID == chainId { + return network, nil + } } - return nil, fmt.Errorf("no RPC provider available for chain ID %d", chainId) + return nil, fmt.Errorf("no EVM network available for chain ID %d", chainId) } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 5cd700a4567..c0a319b8091 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -2,17 +2,14 @@ package test_env import ( "fmt" - "math/big" "os" "slices" "strings" "testing" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" @@ -25,8 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" ) @@ -47,8 +42,6 @@ type ChainlinkNodeLogScannerSettings struct { type CLTestEnvBuilder struct { hasLogStream bool hasKillgrave bool - hasSeth bool - hasEVMClient bool clNodeConfig *chainlink.Config secretsConfig string clNodesCount int @@ -65,9 +58,6 @@ type CLTestEnvBuilder struct { privateEthereumNetworks []*ctf_config.EthereumNetworkConfig testConfig ctf_config.GlobalTestConfig chainlinkNodeLogScannerSettings *ChainlinkNodeLogScannerSettings - - /* funding */ - ETHFunds *big.Float } var DefaultAllowedMessages = []testreporters.AllowedLogMessage{ @@ -94,7 +84,6 @@ func NewCLTestEnvBuilder() *CLTestEnvBuilder { return &CLTestEnvBuilder{ l: log.Logger, hasLogStream: true, - hasEVMClient: true, isEVM: true, chainlinkNodeLogScannerSettings: &DefaultChainlinkNodeLogScannerSettings, } @@ -169,23 +158,6 @@ func (b *CLTestEnvBuilder) WithCLNodeOptions(opt ...ClNodeOption) *CLTestEnvBuil return b } -func (b *CLTestEnvBuilder) WithFunding(eth *big.Float) *CLTestEnvBuilder { - b.ETHFunds = eth - return b -} - -func (b *CLTestEnvBuilder) WithSeth() *CLTestEnvBuilder { - b.hasSeth = true - b.hasEVMClient = false - return b -} - -func (b *CLTestEnvBuilder) WithoutEvmClients() *CLTestEnvBuilder { - b.hasSeth = false - b.hasEVMClient = false - return b -} - func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = append(b.privateEthereumNetworks, &en) return b @@ -379,7 +351,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if len(b.privateEthereumNetworks) > 1 { b.te.rpcProviders = make(map[int64]*test_env.RpcProvider) b.te.EVMNetworks = make([]*blockchain.EVMNetwork, 0) - b.te.evmClients = make(map[int64]blockchain.EVMClient) for _, en := range b.privateEthereumNetworks { en.DockerNetworkNames = []string{b.te.DockerNetwork.Name} networkConfig, rpcProvider, err := b.te.StartEthereumNetwork(en) @@ -387,23 +358,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return nil, err } - if b.hasEVMClient { - evmClient, err := blockchain.NewEVMClientFromNetwork(networkConfig, b.l) - if err != nil { - return nil, err - } - b.te.evmClients[networkConfig.ChainID] = evmClient - } - - if b.hasSeth { - sethClient, err := actions_seth.GetChainClient(b.testConfig, networkConfig) - if err != nil { - return nil, err - } - - b.te.sethClients[networkConfig.ChainID] = sethClient - } - b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) } @@ -469,51 +423,12 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } - if !b.hasSeth && !b.hasEVMClient { - log.Debug().Msg("No EVM client or SETH client specified, not starting any clients") - } - - if b.hasSeth && b.hasEVMClient { - return nil, errors.New("you can't use both Seth and EMVClient at the same time") - } - if b.isEVM { if b.evmNetworkOption != nil && len(b.evmNetworkOption) > 0 { for _, fn := range b.evmNetworkOption { fn(&networkConfig) } } - if b.hasEVMClient { - bc, err := blockchain.NewEVMClientFromNetwork(networkConfig, b.l) - if err != nil { - return nil, err - } - - b.te.evmClients = make(map[int64]blockchain.EVMClient) - b.te.evmClients[networkConfig.ChainID] = bc - - cd, err := contracts.NewContractDeployer(bc, b.l) - if err != nil { - return nil, err - } - b.te.ContractDeployer = cd - - cl, err := contracts.NewContractLoader(bc, b.l) - if err != nil { - return nil, err - } - b.te.ContractLoader = cl - } - - if b.hasSeth { - b.te.sethClients = make(map[int64]*seth.Client) - sethClient, err := actions_seth.GetChainClient(b.testConfig, networkConfig) - if err != nil { - return nil, err - } - - b.te.sethClients[networkConfig.ChainID] = sethClient - } } var nodeCsaKeys []string @@ -563,23 +478,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.defaultNodeCsaKeys = nodeCsaKeys } - if b.clNodesCount > 0 && b.ETHFunds != nil { - if b.hasEVMClient { - b.te.ParallelTransactions(true) - defer b.te.ParallelTransactions(false) - if err := b.te.FundChainlinkNodes(b.ETHFunds); err != nil { - return nil, err - } - } - if b.hasSeth { - for _, sethClient := range b.te.sethClients { - if err := actions_seth.FundChainlinkNodesFromRootAddress(b.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(b.te.ClCluster.NodeAPIs()), b.ETHFunds); err != nil { - return nil, err - } - } - } - } - var enDesc string if len(b.te.PrivateEthereumConfigs) > 0 { for _, en := range b.te.PrivateEthereumConfigs { diff --git a/integration-tests/experiments/gas_test.go b/integration-tests/experiments/gas_test.go index 640187352ed..88bfbcf1926 100644 --- a/integration-tests/experiments/gas_test.go +++ b/integration-tests/experiments/gas_test.go @@ -5,11 +5,13 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) @@ -20,10 +22,10 @@ func TestGasExperiment(t *testing.T) { require.NoError(t, err, "Error getting config") network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - seth, err := actions_seth.GetChainClient(&config, network) + seth, err := seth_utils.GetChainClient(&config, network) require.NoError(t, err, "Error creating seth client") - _, err = actions_seth.SendFunds(l, seth, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, seth, actions.FundsToSendPayload{ ToAddress: seth.Addresses[0], Amount: big.NewInt(10_000_000), PrivateKey: seth.PrivateKeys[0], diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 7f066aa8bcc..1761e58f861 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -40,8 +40,8 @@ import ( gowiremock "github.com/wiremock/go-wiremock" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -319,8 +319,7 @@ Load Config: require.NoError(t, err, "Error running chainlink DON") testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - - chainClient, err := actions_seth.GetChainClientWithConfigFunction(loadedTestConfig, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(loadedTestConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -393,7 +392,7 @@ Load Config: a.SetupAutomationDeployment(t) - err = actions_seth.FundChainlinkNodesFromRootAddress(l, a.ChainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes[1:]), big.NewFloat(*loadedTestConfig.Common.ChainlinkNodeFunding)) + err = actions.FundChainlinkNodesFromRootAddress(l, a.ChainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes[1:]), big.NewFloat(*loadedTestConfig.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Error funding chainlink nodes") consumerContracts := make([]contracts.KeeperConsumer, 0) @@ -791,7 +790,7 @@ Test Duration: %s` } t.Cleanup(func() { - if err = actions_seth.TeardownRemoteSuite(t, chainClient, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &loadedTestConfig); err != nil { + if err = actions.TeardownRemoteSuite(t, chainClient, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &loadedTestConfig); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") testEnvironment.Cfg.TTL += time.Hour * 48 err := testEnvironment.Run() diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 4fa13149d77..30559743e1d 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -12,7 +12,7 @@ import ( ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" aconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" @@ -97,7 +97,7 @@ type task struct { func deployConsumerAndTriggerContracts(l zerolog.Logger, loadConfig aconfig.Load, chainClient *seth.Client, multicallAddress common.Address, maxConcurrency int, automationDefaultLinkFunds *big.Int, linkToken contracts.LinkToken) (DeploymentData, error) { data := DeploymentData{} - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(chainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(chainClient, 1) if err != nil { return DeploymentData{}, err } @@ -197,7 +197,7 @@ func deployConsumerAndTriggerContracts(l zerolog.Logger, loadConfig aconfig.Load } } - sendErr := actions_seth.SendLinkFundsToDeploymentAddresses(chainClient, concurrency, *loadConfig.NumberOfUpkeeps, *loadConfig.NumberOfUpkeeps/concurrency, multicallAddress, automationDefaultLinkFunds, linkToken) + sendErr := actions.SendLinkFundsToDeploymentAddresses(chainClient, concurrency, *loadConfig.NumberOfUpkeeps, *loadConfig.NumberOfUpkeeps/concurrency, multicallAddress, automationDefaultLinkFunds, linkToken) if sendErr != nil { return DeploymentData{}, sendErr } diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index e6f96ccbdf2..bf1cc54f009 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -8,6 +8,8 @@ import ( "strconv" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" @@ -19,7 +21,6 @@ import ( ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/networks" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types" ) @@ -53,7 +54,7 @@ type S4SecretsCfg struct { func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] - seth, err := actions_seth.GetChainClient(globalConfig, selectedNetwork) + seth, err := seth_utils.GetChainClient(globalConfig, selectedNetwork) if err != nil { return nil, err } diff --git a/integration-tests/load/ocr/helper.go b/integration-tests/load/ocr/helper.go index ad07ccd4fd4..f95bf143bce 100644 --- a/integration-tests/load/ocr/helper.go +++ b/integration-tests/load/ocr/helper.go @@ -13,7 +13,6 @@ import ( client2 "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) @@ -23,7 +22,7 @@ func SetupCluster( seth *seth.Client, workerNodes []*client.ChainlinkK8sClient, ) (common.Address, error) { - err := actions_seth.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(3)) + err := actions.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(3)) if err != nil { return common.Address{}, err } @@ -42,7 +41,7 @@ func SetupFeed( bootstrapNode *client.ChainlinkK8sClient, workerNodes []*client.ChainlinkK8sClient, ) ([]contracts.OffchainAggregator, error) { - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, seth, 1, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, seth, 1, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) if err != nil { return nil, err } diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index e836fda39c6..15f52acbffa 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -3,13 +3,14 @@ package ocr import ( "testing" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/wasp" "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/k8s" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) @@ -30,7 +31,7 @@ func TestOCRLoad(t *testing.T) { evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() require.NoError(t, err) - seth, err := actions_seth.GetChainClient(config, *evmNetwork) + seth, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error creating seth client") lta, err := SetupCluster(l, seth, workerNodes) @@ -66,7 +67,7 @@ func TestOCRVolume(t *testing.T) { evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() require.NoError(t, err) - seth, err := actions_seth.GetChainClient(config, *evmNetwork) + seth, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error creating seth client") lta, err := SetupCluster(l, seth, workerNodes) diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index 83f43a94e4d..88f186c5ee1 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -17,7 +17,6 @@ import ( client2 "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) @@ -79,7 +78,7 @@ func (m *VU) Clone(_ *wasp.Generator) wasp.VirtualUser { } func (m *VU) Setup(_ *wasp.Generator) error { - ocrInstances, err := actions_seth.DeployOCRv1Contracts(m.l, m.seth, 1, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(m.l, m.seth, 1, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) if err != nil { return err } diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index fb144e23a2e..5f7e184a488 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" @@ -15,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -40,6 +41,7 @@ func TestVRFV2Performance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() @@ -59,9 +61,6 @@ func TestVRFV2Performance(t *testing.T) { } network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") - updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -75,7 +74,6 @@ func TestVRFV2Performance(t *testing.T) { Msg("Performance Test Configuration") cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { @@ -106,13 +104,12 @@ func TestVRFV2Performance(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2 universe") var consumers []contracts.VRFv2LoadTestConsumer subIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, vrfContracts.LinkToken, 1, @@ -185,6 +182,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -216,11 +214,9 @@ func TestVRFV2BHSPerformance(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") + cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) - if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -249,16 +245,16 @@ func TestVRFV2BHSPerformance(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2 universe") t.Run("vrfv2 and bhs performance test", func(t *testing.T) { configCopy := testConfig.MustCopy().(tc.TestConfig) //Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) + underfundedSubIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, vrfContracts.LinkToken, 1, diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 05feb6fd5a9..3ff9a12996e 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" @@ -14,12 +16,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -39,6 +40,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() @@ -58,8 +60,6 @@ func TestVRFV2PlusPerformance(t *testing.T) { } network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -74,7 +74,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { cleanupFn := func() { teardown(t, vrfContracts.VRFV2PlusConsumer[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") + if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -101,14 +101,14 @@ func TestVRFV2PlusPerformance(t *testing.T) { NumberOfTxKeysToCreate: *vrfv2PlusConfig.General.NumberOfSendingKeysToCreate, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") var consumers []contracts.VRFv2PlusLoadTestConsumer + subIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testcontext.Get(t), - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, vrfContracts.LinkToken, 1, @@ -182,6 +182,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -213,12 +214,9 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") cleanupFn := func() { teardown(t, vrfContracts.VRFV2PlusConsumer[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -246,7 +244,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { NumberOfTxKeysToCreate: *vrfv2PlusConfig.General.NumberOfSendingKeysToCreate, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("vrfv2plus and bhs performance test", func(t *testing.T) { @@ -257,8 +255,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { underfundedSubIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testcontext.Get(t), - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, vrfContracts.LinkToken, 1, @@ -311,8 +308,6 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { var wgBlockNumberTobe sync.WaitGroup wgBlockNumberTobe.Add(1) //Wait at least 256 blocks - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") latestBlockNumber, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "error getting latest block number") _, err = actions.WaitForBlockNumberToBe( diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index f89644eb815..4c7b275e299 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -33,7 +33,6 @@ func TestVersionUpgrade(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 366f073c998..e41244e55e1 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/onsi/gomega" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -18,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" geth_helm "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -167,24 +168,24 @@ func TestAutomationReorg(t *testing.T) { } gethRPCClient := ctf_client.NewRPCClient(network.HTTPURLs[0]) - chainClient, err := actions_seth.GetChainClient(config, network) + chainClient, err := seth_utils.GetChainClient(config, network) require.NoError(t, err, "Error connecting to blockchain") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) require.NoError(t, err, "Error connecting to Chainlink nodes") // Register cleanup for any test t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) require.NoError(t, err, "Error tearing down environment") }) - err = actions_seth.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), nodeFundsAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), nodeFundsAmount) require.NoError(t, err, "Error funding Chainlink nodes") linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) require.NoError(t, err, "Error deploying LINK token") - registry, registrar := actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, chainClient, registryVersion, @@ -210,7 +211,7 @@ func TestAutomationReorg(t *testing.T) { // Use the name to determine if this is a log trigger or not isLogTrigger := name == "registry_2_1_logtrigger" || name == "registry_2_2_logtrigger" - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, chainClient, registry, diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go deleted file mode 100644 index a5659e66783..00000000000 --- a/integration-tests/reorg/reorg_confirmer.go +++ /dev/null @@ -1,284 +0,0 @@ -package reorg - -import ( - "context" - "fmt" - "math/big" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog/log" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" -) - -// The steps are: -// 1. Await initial network consensus for N blocks -// 2. Fork the network, separate node 0 from 1 and 2 -// 3. Await alternative blocks mined on node zero, -// nodes 1 and 2 will have longer chain with more block difficulty so blocks of node 0 must be replaced -// 4. Await consensus for N blocks, check alt block hashes now -const ( - InitConsensus int64 = iota - NetworkFork - CheckBlocks - Consensus - Wait -) - -type ReorgConfig struct { - FromPodLabel string - ToPodLabel string - Network blockchain.EVMClient - Env *environment.Environment - BlockConsensusThreshold int - Timeout time.Duration -} - -// ReorgController reorg stats collecting struct -type ReorgController struct { - cfg *ReorgConfig - ReorgDepth int - numberOfNodes int - currentBlockConsensus int - forkBlockNumber int64 - currentAltBlocks int - currentVerifiedBlocks int - networkStep atomic.Int64 - altBlockNumbers []int64 - blocksByNode map[int]map[int64]blockchain.NodeHeader - blockHashes map[int64][]common.Hash - chaosExperimentName string - initConsensusReady chan struct{} - reorgStarted chan struct{} - depthReached chan struct{} - once sync.Once - mutex sync.Mutex - ctx context.Context - cancel context.CancelFunc - doneChan chan struct{} - complete bool -} - -// NewReorgController creates a type that can create reorg chaos and confirm reorg has happened -func NewReorgController(cfg *ReorgConfig) (*ReorgController, error) { - if len(cfg.Network.GetClients()) == 1 { - return nil, fmt.Errorf("need at least 3 nodes to re-org") - } - ctx, ctxCancel := context.WithTimeout(context.Background(), cfg.Timeout) - rc := &ReorgController{ - cfg: cfg, - numberOfNodes: len(cfg.Network.GetClients()), - doneChan: make(chan struct{}, 100), - altBlockNumbers: make([]int64, 0), - blockHashes: map[int64][]common.Hash{}, - blocksByNode: map[int]map[int64]blockchain.NodeHeader{}, - initConsensusReady: make(chan struct{}, 100), - reorgStarted: make(chan struct{}, 100), - depthReached: make(chan struct{}, 100), - ctx: ctx, - cancel: ctxCancel, - } - rc.networkStep.Store(InitConsensus) - for _, c := range cfg.Network.GetClients() { - c.AddHeaderEventSubscription("reorg", rc) - } - <-rc.initConsensusReady - return rc, nil -} - -// ReOrg start re-org -func (rc *ReorgController) ReOrg(depth int) { - rc.ReorgDepth = depth - rc.networkStep.Store(NetworkFork) -} - -// WaitDepthReached wait until N alternative blocks are mined -func (rc *ReorgController) WaitDepthReached() error { - <-rc.depthReached - rc.networkStep.Store(Consensus) - return rc.cfg.Network.WaitForEvents() -} - -// WaitReorgStarted waits until first alternative block is present -func (rc *ReorgController) WaitReorgStarted() { - <-rc.reorgStarted -} - -// ReceiveHeader receives header marked by node that mined it, -// forks the network and record all alternative block numbers on node 0 -func (rc *ReorgController) ReceiveHeader(header blockchain.NodeHeader) error { - rc.mutex.Lock() - defer rc.mutex.Unlock() - rc.appendBlockHeader(header) - switch rc.networkStep.Load() { - case Wait: - case InitConsensus: - if rc.hasNetworkFormedConsensus(header) { - rc.networkStep.Store(Wait) - rc.initConsensusReady <- struct{}{} - } - case NetworkFork: - if err := rc.forkNetwork(header); err != nil { - return err - } - case CheckBlocks: - if err := rc.compareBlocks(header); err != nil { - return err - } - case Consensus: - if rc.hasNetworkFormedConsensus(header) { - rc.complete = true - rc.cancel() - } - } - return nil -} - -func (rc *ReorgController) Complete() bool { - return rc.complete -} - -// VerifyReorgComplete verifies that all blocks are replaced by reorg -func (rc *ReorgController) VerifyReorgComplete() error { - // we are excluding the last block because we can't control joining while blocks were mined - for _, ab := range rc.altBlockNumbers[:len(rc.altBlockNumbers)-1] { - bb := rc.blocksByNode[0][ab] - h, err := rc.cfg.Network.HeaderHashByNumber(context.Background(), big.NewInt(ab)) - if err != nil { - return err - } - log.Info(). - Int64("Number", bb.Number.Int64()). - Str("Hash before", bb.Hash.String()). - Str("Hash after", h). - Msg("Comparing block") - if bb.Hash.String() != h { - rc.currentVerifiedBlocks++ - } - } - if rc.currentVerifiedBlocks+1 < rc.ReorgDepth { - return fmt.Errorf("Reorg depth has not met") - } - return nil -} - -func (rc *ReorgController) isAltBlock(blk blockchain.NodeHeader) bool { - blockNumber := blk.Number.Int64() - // If we've received the same block number from all nodes, check hashes there are some different versions - if len(rc.blockHashes[blockNumber]) >= rc.numberOfNodes { - firstBlockHash := rc.blockHashes[blockNumber][0] - for _, blockHash := range rc.blockHashes[blockNumber][1:] { - if blockHash.String() != firstBlockHash.String() { - return true - } - } - } - return false -} - -func (rc *ReorgController) compareBlocks(blk blockchain.NodeHeader) error { - if blk.NodeID == 0 && blk.Number.Int64() >= rc.forkBlockNumber && rc.isAltBlock(blk) { - rc.once.Do(func() { - log.Warn().Int64("Number", blk.Number.Int64()).Msg("Reorg started") - rc.reorgStarted <- struct{}{} - }) - rc.altBlockNumbers = append(rc.altBlockNumbers, blk.Number.Int64()) - rc.currentAltBlocks++ - log.Info(). - Int64("Number", blk.Number.Int64()). - Str("Hash", blk.Hash.String()). - Int("Node", blk.NodeID). - Int("BlocksLeft", rc.ReorgDepth-rc.currentAltBlocks). - Msg("Mined alternative block") - } - if rc.currentAltBlocks == rc.ReorgDepth { - log.Info().Msg("Joining network") - if err := rc.joinNetwork(); err != nil { - return err - } - rc.depthReached <- struct{}{} - rc.currentBlockConsensus = 0 - } - return nil -} - -// Wait wait until reorg is done -func (rc *ReorgController) Wait() error { - <-rc.ctx.Done() - rc.cfg.Network.DeleteHeaderEventSubscription("reorg") - if rc.complete { - return nil - } - return fmt.Errorf("timeout waiting for reorg to complete") -} - -// forkNetwork stomp the network between target reorged node and the rest -func (rc *ReorgController) forkNetwork(header blockchain.NodeHeader) error { - rc.forkBlockNumber = header.Number.Int64() - log.Debug(). - Int64("Number", rc.forkBlockNumber). - Str("Network", rc.cfg.Network.GetNetworkName()). - Msg("Forking network") - expName, err := rc.cfg.Env.Chaos.Run( - chaos.NewNetworkPartition( - rc.cfg.Env.Cfg.Namespace, - &chaos.Props{ - DurationStr: "999h", - FromLabels: &map[string]*string{"app": ptr.Ptr(reorg.TXNodesAppLabel)}, - ToLabels: &map[string]*string{"app": ptr.Ptr(reorg.MinerNodesAppLabel)}, - }, - )) - rc.chaosExperimentName = expName - rc.networkStep.Store(CheckBlocks) - return err -} - -// joinNetwork restores network connectivity between nodes -func (rc *ReorgController) joinNetwork() error { - return rc.cfg.Env.Chaos.Stop(rc.chaosExperimentName) -} - -// hasNetworkFormedConsensus waits for network to have N blocks with the same hashes -func (rc *ReorgController) hasNetworkFormedConsensus(header blockchain.NodeHeader) bool { - blockNumber := header.Number.Int64() - // If we've received the same block number from all nodes, check hashes to ensure they've reformed consensus - if len(rc.blockHashes[blockNumber]) >= rc.numberOfNodes { - firstBlockHash := rc.blockHashes[blockNumber][0] - for _, blockHash := range rc.blockHashes[blockNumber][1:] { - if blockHash.String() != firstBlockHash.String() { - return false - } - } - log.Debug(). - Int("Blocks left", rc.cfg.BlockConsensusThreshold-rc.currentBlockConsensus). - Msg("Waiting for consensus threshold") - rc.currentBlockConsensus++ - } - - if rc.currentBlockConsensus >= rc.cfg.BlockConsensusThreshold { - log.Info(). - Msg("Network joined") - return true - } - return false -} - -func (rc *ReorgController) appendBlockHeader(header blockchain.NodeHeader) { - bn := header.Number.Int64() - if _, ok := rc.blockHashes[bn]; !ok { - rc.blockHashes[bn] = []common.Hash{} - } - rc.blockHashes[bn] = append(rc.blockHashes[bn], header.Hash) - - if _, ok := rc.blocksByNode[header.NodeID]; !ok { - rc.blocksByNode[header.NodeID] = make(map[int64]blockchain.NodeHeader) - } - rc.blocksByNode[header.NodeID][bn] = header -} diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index cafeea67c19..50b5fb96230 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/fxamacker/cbor/v2" @@ -22,10 +24,8 @@ import ( ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -37,7 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" ) const ( @@ -47,6 +47,20 @@ const ( defaultAmountOfUpkeeps = 2 ) +// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment +// to apply the upgrades +func upgradeChainlinkNodeVersionsLocal( + newImage, newVersion string, + nodes ...*test_env.ClNode, +) error { + for _, node := range nodes { + if err := node.UpgradeVersion(newImage, newVersion); err != nil { + return err + } + } + return nil +} + func automationDefaultRegistryConfig(c tc.AutomationTestConfig) contracts.KeeperRegistrySettings { registrySettings := c.GetAutomationConfig().AutomationConfig.RegistrySettings return contracts.KeeperRegistrySettings{ @@ -127,7 +141,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -171,7 +185,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { startTime := time.Now() t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) // TODO Tune this timeout window after stress testing @@ -195,7 +209,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { expect := 5 // Upgrade the nodes one at a time and check that the upkeeps are still being performed for i := 0; i < 5; i++ { - err = actions.UpgradeChainlinkNodeVersionsLocal(*cfg.GetChainlinkUpgradeImageConfig().Image, *cfg.GetChainlinkUpgradeImageConfig().Version, a.DockerEnv.ClCluster.Nodes[i]) + err = upgradeChainlinkNodeVersionsLocal(*cfg.GetChainlinkUpgradeImageConfig().Image, *cfg.GetChainlinkUpgradeImageConfig().Version, a.DockerEnv.ClCluster.Nodes[i]) require.NoError(t, err, "Error when upgrading node %d", i) time.Sleep(time.Second * 10) expect = expect + 5 @@ -266,7 +280,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -288,7 +302,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { } t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) l.Info().Msg("Waiting for all upkeeps to perform") @@ -447,7 +461,7 @@ func TestAutomationAddFunds(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -461,7 +475,7 @@ func TestAutomationAddFunds(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) l.Info().Msg("Making sure for 2m no upkeeps are performed") @@ -525,7 +539,7 @@ func TestAutomationPauseUnPause(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -539,7 +553,7 @@ func TestAutomationPauseUnPause(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -624,7 +638,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -638,7 +652,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -659,7 +673,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { } }, "4m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer - newConsumers, _ := actions_seth.RegisterNewUpkeeps(t, a.ChainClient, a.LinkToken, + newConsumers, _ := actions.RegisterNewUpkeeps(t, a.ChainClient, a.LinkToken, a.Registry, a.Registrar, automationDefaultUpkeepGasLimit, 1) // We know that newConsumers has size 1, so we can just use the newly registered upkeep. @@ -718,7 +732,7 @@ func TestAutomationPauseRegistry(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -732,7 +746,7 @@ func TestAutomationPauseRegistry(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -796,7 +810,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -810,7 +824,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -902,7 +916,7 @@ func TestAutomationPerformSimulation(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumersPerformance, _ := actions_seth.DeployPerformanceConsumers( + consumersPerformance, _ := actions.DeployPerformanceConsumers( t, a.ChainClient, a.Registry, @@ -918,7 +932,7 @@ func TestAutomationPerformSimulation(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -973,7 +987,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceConsumers( + consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers( t, a.ChainClient, a.Registry, @@ -989,7 +1003,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1128,7 +1142,7 @@ func TestUpdateCheckData(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - performDataChecker, upkeepIDs := actions_seth.DeployPerformDataCheckerConsumers( + performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers( t, a.ChainClient, a.Registry, @@ -1141,7 +1155,7 @@ func TestUpdateCheckData(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1209,7 +1223,7 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -1223,7 +1237,7 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1348,7 +1362,6 @@ func setupAutomationTestDocker( l := logging.GetTestLogger(t) // Add registry version to config registryConfig.RegistryVersion = registryVersion - network := networks.MustGetSelectedNetworkConfig(automationTestConfig.GetNetworkConfig())[0] //launch the environment var env *test_env.CLClusterTestEnv @@ -1366,7 +1379,6 @@ func setupAutomationTestDocker( WithTestInstance(t). WithTestConfig(automationTestConfig). WithMockAdapter(). - WithoutEvmClients(). WithoutCleanup(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") @@ -1388,9 +1400,7 @@ func setupAutomationTestDocker( WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithSecretsConfig(secretsConfig). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") @@ -1402,18 +1412,27 @@ func setupAutomationTestDocker( WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") } nodeClients := env.ClCluster.NodeAPIs() - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(automationTestConfig, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients) a.SetMercuryCredentialName("cred1") a.RegistrySettings = registryConfig diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index e281824f0bb..6f864b2e49f 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -36,7 +36,6 @@ func TestCronBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -92,7 +91,6 @@ func TestCronJobReplacement(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 4165e9b79b7..05b75da2237 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -13,11 +13,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -29,9 +28,7 @@ func TestFluxBasic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.Flux) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -43,15 +40,16 @@ func TestFluxBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(3). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) nodeAddresses, err := env.ClCluster.NodeAddresses() require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") adapterUUID := uuid.NewString() @@ -71,9 +69,14 @@ func TestFluxBasic(t *testing.T) { err = fluxInstance.UpdateAvailableFunds() require.NoError(t, err, "Updating the available funds on the Flux Aggregator Contract shouldn't fail") - err = env.FundChainlinkNodes(big.NewFloat(1)) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Failed to fund the nodes") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + err = fluxInstance.SetOracles( contracts.FluxAggregatorSetOraclesOptions{ AddList: nodeAddresses, @@ -115,7 +118,7 @@ func TestFluxBasic(t *testing.T) { // initial value set is performed before jobs creation fluxRoundTimeout := 1 * time.Minute - err = actions_seth.WatchNewFluxRound(l, sethClient, 1, fluxInstance, fluxRoundTimeout) + err = actions.WatchNewFluxRound(l, sethClient, 1, fluxInstance, fluxRoundTimeout) require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") data, err := fluxInstance.GetContractData(testcontext.Get(t)) require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") @@ -132,7 +135,7 @@ func TestFluxBasic(t *testing.T) { err = env.MockAdapter.SetAdapterBasedIntValuePath(adapterPath, []string{http.MethodPost}, 1e10) require.NoError(t, err, "Setting value path in mock server shouldn't fail") - err = actions_seth.WatchNewFluxRound(l, sethClient, 2, fluxInstance, fluxRoundTimeout) + err = actions.WatchNewFluxRound(l, sethClient, 2, fluxInstance, fluxRoundTimeout) require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") data, err = fluxInstance.GetContractData(testcontext.Get(t)) require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 1783549637b..0377553191b 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -6,15 +6,15 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -25,9 +25,7 @@ func TestForwarderOCRBasic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.ForwarderOcr) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -38,9 +36,7 @@ func TestForwarderOCRBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -50,32 +46,42 @@ func TestForwarderOCRBasic(t *testing.T) { workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) require.NoError(t, err, "Error funding Chainlink nodes") - operators, authorizedForwarders, _ := actions_seth.DeployForwarderContracts( + operators, authorizedForwarders, _ := actions.DeployForwarderContracts( t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") for i := range workerNodes { - actions_seth.AcceptAuthorizedReceiversOperator( + actions.AcceptAuthorizedReceiversOperator( t, l, sethClient, operators[i], authorizedForwarders[i], []common.Address{workerNodeAddresses[i]}, ) require.NoError(t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions_seth.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) + actions.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) } - ocrInstances, err := actions_seth.DeployOCRContractsForwarderFlow( + ocrInstances, err := actions.DeployOCRContractsForwarderFlow( l, sethClient, 1, @@ -87,7 +93,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, fmt.Sprint(sethClient.ChainID)) require.NoError(t, err, "failed to setup forwarder jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCR round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -96,7 +102,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCR round") answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 2651a02fb4d..3970a0b43b1 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -7,15 +7,15 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -26,9 +26,7 @@ func TestForwarderOCR2Basic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.ForwarderOcr2) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -39,9 +37,7 @@ func TestForwarderOCR2Basic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -51,30 +47,40 @@ func TestForwarderOCR2Basic(t *testing.T) { workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) require.NoError(t, err, "Error funding Chainlink nodes") - operators, authorizedForwarders, _ := actions_seth.DeployForwarderContracts( + operators, authorizedForwarders, _ := actions.DeployForwarderContracts( t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") for i := range workerNodes { - actions_seth.AcceptAuthorizedReceiversOperator( + actions.AcceptAuthorizedReceiversOperator( t, l, sethClient, operators[i], authorizedForwarders[i], []common.Address{workerNodeAddresses[i]}, ) require.NoError(t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions_seth.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) + actions.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) } // Gather transmitters @@ -84,20 +90,20 @@ func TestForwarderOCR2Basic(t *testing.T) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - ocrInstances, err := actions_seth.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(lt.Address()), transmitters, ocrOffchainOptions) + ocrInstances, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(lt.Address()), transmitters, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 contracts with forwarders") ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) require.NoError(t, err, "Error building OCRv2 config") ocrv2Config.Transmitters = authorizedForwarders - err = actions_seth.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) + err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) require.NoError(t, err, "Error creating OCRv2 jobs with forwarders") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCRv2 round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -108,7 +114,7 @@ func TestForwarderOCR2Basic(t *testing.T) { ocrRoundVal := (5 + i) % 10 err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, ocrRoundVal) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, int64(i), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, int64(i), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCRv2 round") answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) require.NoError(t, err, "Error getting latest OCRv2 answer") diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 62a79f0347b..21e1aa6e08f 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" "github.com/rs/zerolog" @@ -15,11 +17,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -97,7 +97,7 @@ func TestKeeperBasicSmoke(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -109,7 +109,7 @@ func TestKeeperBasicSmoke(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, fmt.Sprint(chainClient.ChainID)) @@ -178,7 +178,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, highBCPTRegistryConfig, @@ -193,7 +193,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) keepersPerformedLowFreq := map[*big.Int][]string{} @@ -322,7 +322,7 @@ func TestKeeperSimulation(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceKeeperContracts( + registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, chainClient, registryVersion, @@ -341,7 +341,7 @@ func TestKeeperSimulation(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) consumerPerformance := consumersPerformance[0] @@ -401,7 +401,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceKeeperContracts( + registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, chainClient, registryVersion, @@ -420,7 +420,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -538,7 +538,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, registrar, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, registrar, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -552,7 +552,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -576,7 +576,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { return nil }, "1m", "1s").Should(gomega.Succeed()) - newConsumers, _ := actions_seth.RegisterNewUpkeeps(t, chainClient, linkToken, + newConsumers, _ := actions.RegisterNewUpkeeps(t, chainClient, linkToken, registry, registrar, keeperDefaultUpkeepGasLimit, 1) // We know that newConsumers has size 1, so we can just use the newly registered upkeep. @@ -634,7 +634,7 @@ func TestKeeperAddFunds(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -649,7 +649,7 @@ func TestKeeperAddFunds(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) // Since the upkeep is currently underfunded, check that it doesn't get executed @@ -709,7 +709,7 @@ func TestKeeperRemove(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -724,7 +724,7 @@ func TestKeeperRemove(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -794,7 +794,7 @@ func TestKeeperPauseRegistry(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -810,7 +810,7 @@ func TestKeeperPauseRegistry(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) // Observe that the upkeeps which are initially registered are performing @@ -860,7 +860,7 @@ func TestKeeperMigrateRegistry(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_2, keeperDefaultRegistryConfig, @@ -875,11 +875,11 @@ func TestKeeperMigrateRegistry(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_2)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_2)() }) // Deploy the second registry, second registrar, and the same number of upkeeps as the first one - secondRegistry, _, _, _ := actions_seth.DeployKeeperContracts( + secondRegistry, _, _, _ := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_2, keeperDefaultRegistryConfig, @@ -964,7 +964,7 @@ func TestKeeperNodeDown(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, lowBCPTRegistryConfig, @@ -979,7 +979,7 @@ func TestKeeperNodeDown(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -1074,7 +1074,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_3, lowBCPTRegistryConfig, @@ -1089,7 +1089,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() }) gom := gomega.NewGomegaWithT(t) @@ -1166,7 +1166,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, performDataChecker, upkeepIDs := actions_seth.DeployPerformDataCheckerContracts( + registry, _, performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerContracts( t, chainClient, ethereum.RegistryVersion_1_3, @@ -1182,7 +1182,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() }) gom := gomega.NewGomegaWithT(t) @@ -1236,16 +1236,23 @@ func setupKeeperTest(l zerolog.Logger, t *testing.T, config *tc.TestConfig) ( WithTestConfig(config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(5). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) + require.NoError(t, err, "Error getting seth client") + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") - sethClient, err := env.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting EVM client shouldn't fail") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) linkTokenContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") @@ -1261,7 +1268,7 @@ func TestKeeperJobReplacement(t *testing.T) { require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index 1f77b3a6250..05be29a90bc 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/onsi/gomega" "github.com/rs/zerolog" @@ -14,10 +16,9 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -94,7 +95,7 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) - eventsToEmit := []abi.Event{} + var eventsToEmit []abi.Event for _, event := range logpoller.EmitterABI.Events { eventsToEmit = append(eventsToEmit, event) } @@ -107,6 +108,12 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli lpTestEnv := prepareEnvironment(l, t, &testConfig, logScannerSettings) testEnv := lpTestEnv.testEnv + sethClient := lpTestEnv.sethClient + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) ctx := testcontext.Get(t) @@ -117,12 +124,8 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli l.Info().Msg("No duplicate filters found. OK!") - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - expectedFilters := logpoller.GetExpectedFilters(lpTestEnv.logEmitters, cfg) - waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, testEnv, &testConfig, expectedFilters) + waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, lpTestEnv, expectedFilters) // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) @@ -135,7 +138,7 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli // Start chaos experimnents by randomly pausing random containers (Chainlink nodes or their DBs) chaosDoneCh := make(chan error, 1) go func() { - logpoller.ExecuteChaosExperiment(l, testEnv, &testConfig, chaosDoneCh) + logpoller.ExecuteChaosExperiment(l, testEnv, sethClient, &testConfig, chaosDoneCh) }() totalLogsEmitted, err := logpoller.ExecuteGenerator(t, cfg, sethClient, lpTestEnv.logEmitters) @@ -175,7 +178,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) - eventsToEmit := []abi.Event{} + var eventsToEmit []abi.Event for _, event := range logpoller.EmitterABI.Events { eventsToEmit = append(eventsToEmit, event) } @@ -188,11 +191,16 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { lpTestEnv := prepareEnvironment(l, t, &testConfig, test_env.DefaultChainlinkNodeLogScannerSettings) testEnv := lpTestEnv.testEnv + sethClient := lpTestEnv.sethClient + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) ctx := testcontext.Get(t) - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) @@ -211,7 +219,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { eb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") - endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), network, cfg) + endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), *evmNetwork, cfg) require.NoError(t, err, "Error getting end block to wait for") l.Info().Int64("Ending Block", endBlock).Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION") @@ -228,7 +236,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { err = logpoller.RegisterFiltersAndAssertUniquness(l, lpTestEnv.registry, lpTestEnv.upkeepIDs, lpTestEnv.logEmitters, cfg, lpTestEnv.upKeepsNeeded) require.NoError(t, err, "Error registering filters") - waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, testEnv, &testConfig, expectedFilters) + waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, lpTestEnv, expectedFilters) blockFinalisationWaitDuration := "5m" l.Warn().Str("Duration", blockFinalisationWaitDuration).Msg("Waiting for all CL nodes to have end block finalised") @@ -262,6 +270,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { } type logPollerEnvironment struct { + sethClient *seth.Client logEmitters []*contracts.LogEmitter testEnv *test_env.CLClusterTestEnv registry contracts.KeeperRegistry @@ -297,7 +306,7 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi logScannerSettings, ) - _, upkeepIDs := actions_seth.DeployConsumers( + _, upkeepIDs := actions.DeployConsumers( t, chainClient, registry, @@ -326,16 +335,16 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi upkeepIDs: upkeepIDs, upKeepsNeeded: upKeepsNeeded, testEnv: testEnv, + sethClient: chainClient, } } // waitForAllNodesToHaveExpectedFiltersRegisteredOrFail waits until all nodes have expected filters registered until timeout -func waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx context.Context, l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, testEnv *test_env.CLClusterTestEnv, testConfig *tc.TestConfig, expectedFilters []logpoller.ExpectedFilter) { +func waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx context.Context, l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, lpTestEnv logPollerEnvironment, expectedFilters []logpoller.ExpectedFilter) { // Make sure that all nodes have expected filters registered before starting to emit events - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + sethClient := lpTestEnv.sethClient + testEnv := lpTestEnv.testEnv gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { @@ -372,13 +381,9 @@ func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogge logCountWaitDuration, err := time.ParseDuration(waitDuration) require.NoError(t, err, "Error parsing log count wait duration") - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - chainClient, err := lpTestEnv.testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - allNodesHaveAllExpectedLogs := false if !allNodesLogCountMatches { - missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, chainClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) + missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, lpTestEnv.sethClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) if err == nil { if !missingLogs.IsEmpty() { logpoller.PrintMissingLogsInfo(missingLogs, l, testConfig.LogPoller) @@ -402,7 +407,7 @@ func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogge gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { - missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, chainClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) + missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, lpTestEnv.sethClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) if err != nil { l.Warn(). Err(err). diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index d0d1e36c8ed..09a9a222494 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" @@ -15,13 +17,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -62,7 +62,7 @@ func TestOCRv2Basic(t *testing.T) { err := testEnv.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err) roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) @@ -84,9 +84,9 @@ func TestOCRv2Request(t *testing.T) { // Keep the mockserver value the same and continually request new rounds for round := 2; round <= 4; round++ { - err := actions_seth.StartNewRound(contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts)) + err := actions.StartNewRound(contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts)) require.NoError(t, err, "Error starting new OCR2 round") - err = actions_seth.WatchNewOCRRound(l, sethClient, int64(round), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, int64(round), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(int64(round))) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -108,7 +108,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err := env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) @@ -127,7 +127,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) require.NoError(t, err, "Error creating OCRv2 jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) + err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(3)) @@ -156,14 +156,14 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, WithMockAdapter(). WithCLNodes(clNodeCount). WithCLNodeOptions(test_env.WithNodeEnvVars(testData.env)). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := testEnv.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") nodeClients := testEnv.ClCluster.NodeAPIs() @@ -172,9 +172,14 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Error deploying link token contract") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(.05)) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Error funding Chainlink nodes") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) + // Gather transmitters var transmitters []string for _, node := range workerNodes { @@ -186,7 +191,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - aggregatorContracts, err := actions_seth.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) + aggregatorContracts, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) @@ -195,12 +200,12 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) require.NoError(t, err, "Error building OCRv2 config") - err = actions_seth.ConfigureOCRv2AggregatorContracts(ocrv2Config, aggregatorContracts) + err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, aggregatorContracts) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") assertCorrectNodeConfiguration(t, l, clNodeCount, testData, testEnv) - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1)) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -214,7 +219,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, func assertCorrectNodeConfiguration(t *testing.T, l zerolog.Logger, totalNodeCount int, testData ocr2test, testEnv *test_env.CLClusterTestEnv) { expectedNodesWithConfiguration := totalNodeCount - 1 // minus bootstrap node - expectedPatterns := []string{} + var expectedPatterns []string if testData.env[string(env.MedianPlugin.Cmd)] != "" { expectedPatterns = append(expectedPatterns, "Registered loopp.*OCR2.*Median.*") diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go index fe6515df03f..b99e313a026 100644 --- a/integration-tests/smoke/ocr2vrf_test.go +++ b/integration-tests/smoke/ocr2vrf_test.go @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -33,10 +32,10 @@ var ocr2vrfSmokeConfig *testconfig.TestConfig func TestOCR2VRFRedeemModel(t *testing.T) { t.Parallel() - // remember to add TOML config for Chainlink node before trying to run this test in future + // remember to add TOML testConfig for Chainlink node before trying to run this test in future t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - config, err := testconfig.GetConfig("Smoke", testconfig.OCR2) + testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2) if err != nil { t.Fatal(err) } @@ -47,7 +46,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { } testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -56,7 +55,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &testConfig) require.NoError(t, err, "Error tearing down environment") }) @@ -99,7 +98,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { t.Parallel() t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - config, err := testconfig.GetConfig("Smoke", testconfig.OCR2) + testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2) if err != nil { t.Fatal(err) } @@ -110,7 +109,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { } testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -119,7 +118,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &testConfig) require.NoError(t, err, "Error tearing down environment") }) @@ -160,9 +159,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { if ocr2vrfSmokeConfig == nil { c, err := testconfig.GetConfig("Smoke", testconfig.OCR2VRF) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") ocr2vrfSmokeConfig = &c } diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 02d548f4763..d989517278e 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -5,17 +5,17 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -36,7 +36,7 @@ func TestOCRBasic(t *testing.T) { err := actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err, "Error setting all adapter responses to the same value") - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -54,7 +54,7 @@ func TestOCRJobReplacement(t *testing.T) { err := actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err, "Error setting all adapter responses to the same value") - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -71,7 +71,7 @@ func TestOCRJobReplacement(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, big.NewInt(sethClient.ChainID)) require.NoError(t, err, "Error creating OCR jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -94,29 +94,37 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Error funding Chainlink nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Error deploying link token contract") - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err, "Error deploying OCR contracts") err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, big.NewInt(sethClient.ChainID)) require.NoError(t, err, "Error creating OCR jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, "Error watching for new OCR round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go index 7ab76b4c164..829aa66fdce 100644 --- a/integration-tests/smoke/reorg_above_finality_test.go +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -1,7 +1,6 @@ package smoke import ( - "log" "testing" "time" @@ -29,9 +28,7 @@ func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { // Get values from the node config configMap := make(map[string]interface{}) err = toml.Unmarshal([]byte(config.NodeConfig.CommonChainConfigTOML), &configMap) - if err != nil { - log.Fatalf("Error unmarshaling TOML: %s", err) - } + require.NoError(t, err, "Error unmarshaling TOML") nodeFinalityDepthInt, isFinalityDepthSet := configMap["FinalityDepth"].(int64) nodeFinalityTagEnabled := configMap["FinalityTagEnabled"].(bool) l.Info().Int64("nodeFinalityDepth", nodeFinalityDepthInt).Bool("nodeFinalityTagEnabled", nodeFinalityTagEnabled).Msg("Node reorg config") @@ -50,12 +47,13 @@ func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { WithPrivateEthereumNetwork(privateNetworkConf.EthereumNetworkConfig). WithCLNodes(6). WithoutCleanup(). - WithSeth(). Build() require.NoError(t, err) - network := testEnv.EVMNetworks[0] - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0]) // Wait for chain to progress require.Eventually(t, func() bool { diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 7090564c42e..862ac911b36 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -7,12 +7,13 @@ import ( "strings" "testing" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/google/uuid" "github.com/onsi/gomega" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -39,16 +40,24 @@ func TestRunLogBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index abb619e7b0b..0f706f1576b 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -13,12 +13,13 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv1" "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ethcontracts "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -27,7 +28,7 @@ import ( func TestVRFBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - env, contracts, sethClient := prepareVRFtestEnv(t, l) + env, vrfContracts, sethClient := prepareVRFtestEnv(t, l) for _, n := range env.ClCluster.Nodes { nodeKey, err := n.API.MustCreateVRFKey() @@ -36,13 +37,13 @@ func TestVRFBasic(t *testing.T) { pubKeyCompressed := nodeKey.Data.ID jobUUID := uuid.New() os := &client.VRFTxPipelineSpec{ - Address: contracts.Coordinator.Address(), + Address: vrfContracts.Coordinator.Address(), } ost, err := os.String() require.NoError(t, err, "Building observation source spec shouldn't fail") job, err := n.API.MustCreateJob(&client.VRFJobSpec{ Name: fmt.Sprintf("vrf-%s", jobUUID), - CoordinatorAddress: contracts.Coordinator.Address(), + CoordinatorAddress: vrfContracts.Coordinator.Address(), MinIncomingConfirmations: 1, PublicKey: pubKeyCompressed, ExternalJobID: jobUUID.String(), @@ -55,7 +56,7 @@ func TestVRFBasic(t *testing.T) { require.NoError(t, err, "Getting primary ETH address of chainlink node shouldn't fail") provingKey, err := actions.EncodeOnChainVRFProvingKey(*nodeKey) require.NoError(t, err, "Encoding on-chain VRF Proving key shouldn't fail") - err = contracts.Coordinator.RegisterProvingKey( + err = vrfContracts.Coordinator.RegisterProvingKey( big.NewInt(1), oracleAddr, provingKey, @@ -66,9 +67,9 @@ func TestVRFBasic(t *testing.T) { encodedProvingKeys = append(encodedProvingKeys, provingKey) //nolint:gosec // G602 - requestHash, err := contracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0]) + requestHash, err := vrfContracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0]) require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail") - err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1)) + err = vrfContracts.Consumer.RequestRandomness(requestHash, big.NewInt(1)) require.NoError(t, err, "Requesting randomness shouldn't fail") gom := gomega.NewGomegaWithT(t) @@ -77,7 +78,7 @@ func TestVRFBasic(t *testing.T) { jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail") - out, err := contracts.Consumer.RandomnessOutput(testcontext.Get(t)) + out, err := vrfContracts.Consumer.RandomnessOutput(testcontext.Get(t)) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail") // Checks that the job has actually run g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1), @@ -196,25 +197,33 @@ func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestE WithTestConfig(&config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) + require.NoError(t, err, "Error getting seth client") + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) lt, err := ethcontracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - contracts, err := vrfv1.DeployVRFContracts(sethClient, lt.Address()) + vrfContracts, err := vrfv1.DeployVRFContracts(sethClient, lt.Address()) require.NoError(t, err, "Deploying VRF Contracts shouldn't fail") - err = lt.Transfer(contracts.Consumer.Address(), big.NewInt(2e18)) + err = lt.Transfer(vrfContracts.Consumer.Address(), big.NewInt(2e18)) require.NoError(t, err, "Funding consumer contract shouldn't fail") _, err = ethcontracts.DeployVRFv1Contract(sethClient) require.NoError(t, err, "Deploying VRF contract shouldn't fail") - return env, contracts, sethClient + return env, vrfContracts, sethClient } diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 18a017110c7..70fcb4bcf7d 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -46,6 +48,7 @@ func TestVRFv2Basic(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -55,8 +58,6 @@ func TestVRFv2Basic(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -85,17 +86,13 @@ func TestVRFv2Basic(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - t.Run("Request Randomness", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForRequestRandomness, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -151,8 +148,7 @@ func TestVRFv2Basic(t *testing.T) { testConfig := configCopy.VRFv2.General consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -197,8 +193,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForJobRuns, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -242,8 +237,7 @@ func TestVRFv2Basic(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) wrapperContracts, wrapperSubID, err := vrfv2.SetupVRFV2WrapperEnvironment( testcontext.Get(t), - testEnv, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -320,8 +314,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("Oracle Withdraw", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForOracleWithDraw, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -379,8 +372,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) _, subIDsForCancelling, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -459,8 +451,7 @@ func TestVRFv2Basic(t *testing.T) { configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForOwnerCancelling, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -574,6 +565,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -585,8 +577,6 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { vrfv2Config := config.VRFv2 cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -615,15 +605,14 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForMultipleSendingKeys, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -660,8 +649,6 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { 0, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") fulfillmentTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), randomWordsFulfilledEvent.Raw.TxHash) require.NoError(t, err, "error getting tx from hash") fulfillmentTxFromAddress, err := actions.GetTxFromAddress(fulfillmentTx) @@ -686,6 +673,7 @@ func TestVRFOwner(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -695,8 +683,6 @@ func TestVRFOwner(t *testing.T) { vrfv2Config := config.VRFv2 cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -725,15 +711,14 @@ func TestVRFOwner(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("Request Randomness With Force-Fulfill", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForForceFulfill, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -824,6 +809,7 @@ func TestVRFV2WithBHS(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -833,8 +819,6 @@ func TestVRFV2WithBHS(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -867,7 +851,7 @@ func TestVRFV2WithBHS(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("BHS Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { @@ -880,8 +864,7 @@ func TestVRFV2WithBHS(t *testing.T) { //Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForBHS, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -916,8 +899,6 @@ func TestVRFV2WithBHS(t *testing.T) { var wg sync.WaitGroup wg.Add(1) //Wait at least 256 blocks - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") _, err = actions.WaitForBlockNumberToBe( randRequestBlockNumber+uint64(257), sethClient, @@ -951,8 +932,7 @@ func TestVRFV2WithBHS(t *testing.T) { configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForBHS, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -987,9 +967,6 @@ func TestVRFV2WithBHS(t *testing.T) { _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( @@ -1050,6 +1027,7 @@ func TestVRFV2NodeReorg(t *testing.T) { subIDsForCancellingAfterTest []uint64 defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1062,8 +1040,6 @@ func TestVRFV2NodeReorg(t *testing.T) { } chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1105,15 +1081,11 @@ func TestVRFV2NodeReorg(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2 universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, config, vrfContracts.LinkToken, @@ -1152,11 +1124,11 @@ func TestVRFV2NodeReorg(t *testing.T) { // rewind chain to block number after the request was made, but before the request was fulfilled rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //2. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made @@ -1201,11 +1173,11 @@ func TestVRFV2NodeReorg(t *testing.T) { // rewind chain to block number before the randomness request was made rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //3. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) //4. ensure that chain is reorged and latest block number is less than the block number when request was made @@ -1234,6 +1206,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1243,8 +1216,6 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1273,12 +1244,9 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2 universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill //callback gas limit set by consumer = 500k // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill @@ -1330,8 +1298,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfNode.Job = job consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -1452,8 +1419,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfNode.Job = job consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index d1593373204..b713cdf9409 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -43,6 +45,7 @@ func TestVRFv2Plus(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -52,9 +55,6 @@ func TestVRFv2Plus(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -83,19 +83,16 @@ func TestVRFv2Plus(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - t.Run("Link Billing", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false + consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -153,9 +150,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -211,8 +206,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -253,10 +247,10 @@ func TestVRFv2Plus(t *testing.T) { t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false + consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -293,11 +287,11 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Direct Funding", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( testcontext.Get(t), l, - env, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -408,10 +402,10 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + _, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -514,8 +508,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -659,10 +652,10 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Owner Withdraw", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -749,6 +742,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -758,8 +752,6 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -788,7 +780,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { @@ -797,8 +789,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -831,8 +822,6 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { 0, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") fulfillmentTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), randomWordsFulfilledEvent.Raw.TxHash) require.NoError(t, err, "error getting tx from hash") fulfillmentTxFromAddress, err := actions.GetTxFromAddress(fulfillmentTx) @@ -858,6 +847,7 @@ func TestVRFv2PlusMigration(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -867,8 +857,6 @@ func TestVRFv2PlusMigration(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -897,12 +885,9 @@ func TestVRFv2PlusMigration(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - // Migrate subscription from old coordinator to new coordinator, verify if balances // are moved correctly and requests can be made successfully in the subscription in // new coordinator @@ -911,8 +896,7 @@ func TestVRFv2PlusMigration(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1081,8 +1065,7 @@ func TestVRFv2PlusMigration(t *testing.T) { wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( testcontext.Get(t), l, - env, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -1258,6 +1241,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1267,8 +1251,6 @@ func TestVRFV2PlusWithBHS(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1301,12 +1283,9 @@ func TestVRFV2PlusWithBHS(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - var isNativeBilling = true t.Run("BHS Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { if os.Getenv("TEST_UNSKIP") != "true" { @@ -1319,8 +1298,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1401,8 +1379,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1493,6 +1470,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1502,8 +1480,6 @@ func TestVRFV2PlusWithBHF(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1543,13 +1519,10 @@ func TestVRFV2PlusWithBHF(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse( + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse( testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err) - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - var isNativeBilling = true t.Run("BHF Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) @@ -1559,8 +1532,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1655,6 +1627,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1664,8 +1637,6 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1700,7 +1671,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { config.VRFv2Plus.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) config.VRFv2Plus.General.SubscriptionFundingAmountNative = ptr.Ptr(float64(0)) - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("Timed out request fulfilled after node restart with replay", func(t *testing.T) { @@ -1709,8 +1680,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1826,6 +1796,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1835,8 +1806,6 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1870,13 +1839,12 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) config.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](0) config.VRFv2Plus.General.VRFJobSimulationBlock = ptr.Ptr[string]("pending") - env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, config, vrfContracts.LinkToken, @@ -1922,6 +1890,7 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { subIDsForCancellingAfterTest []*big.Int defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1934,8 +1903,6 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { } chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1976,18 +1943,13 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") var isNativeBilling = true - - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, config, vrfContracts.LinkToken, @@ -2022,11 +1984,11 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { // rewind chain to block number after the request was made, but before the request was fulfilled rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //2. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made @@ -2070,11 +2032,11 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { // rewind chain to block number before the randomness request was made rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //3. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) //4. ensure that chain is reorged and latest block number is less than the block number when request was made @@ -2105,6 +2067,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -2114,8 +2077,6 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -2144,12 +2105,9 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill //callback gas limit set by consumer = 500k // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill @@ -2201,8 +2159,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -2316,8 +2273,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -2383,5 +2339,4 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { // verify that all fulfillments should be in separate txs require.Equal(t, int(randRequestCount), len(singleFulfillmentTxs)) }) - } diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index 401100748d7..b5355a6c3f5 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) @@ -32,7 +32,7 @@ ForwardersEnabled = true` return } t.Cleanup(func() { - if err := actions_seth.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { + if err := actions.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") } }) diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index 789c7de8e3b..f0571fc63a1 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) @@ -64,7 +64,7 @@ func runOCRSoakTest(t *testing.T, config tc.TestConfig, customNetworkTOML string return } t.Cleanup(func() { - if err := actions_seth.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { + if err := actions.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") } }) diff --git a/integration-tests/testsetups/don_evm_chain.go b/integration-tests/testsetups/don_evm_chain.go deleted file mode 100644 index 3ade7f0d69d..00000000000 --- a/integration-tests/testsetups/don_evm_chain.go +++ /dev/null @@ -1,81 +0,0 @@ -package testsetups - -import ( - "testing" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - e "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" -) - -type DonChain struct { - conf *DonChainConfig - EVMClient blockchain.EVMClient - EVMNetwork *blockchain.EVMNetwork - ContractDeployer contracts.ContractDeployer - LinkTokenContract contracts.LinkToken - ChainlinkNodes []*client.ChainlinkK8sClient - Mockserver *ctfClient.MockserverClient - l zerolog.Logger -} - -type DonChainConfig struct { - T *testing.T - Env *e.Environment - EVMNetwork *blockchain.EVMNetwork - EthereumProps *ethereum.Props - ChainlinkValues map[string]interface{} -} - -func NewDonChain(conf *DonChainConfig, logger zerolog.Logger) *DonChain { - return &DonChain{ - conf: conf, - EVMNetwork: conf.EVMNetwork, - l: logger, - } -} - -func (s *DonChain) Deploy() { - var err error - - s.conf.Env.AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(ethereum.New(s.conf.EthereumProps)). - AddHelm(chainlink.New(0, s.conf.ChainlinkValues)) - - err = s.conf.Env.Run() - require.NoError(s.conf.T, err) - - s.initializeClients() -} - -func (s *DonChain) initializeClients() { - var err error - network := *s.conf.EVMNetwork - s.EVMClient, err = blockchain.NewEVMClient(network, s.conf.Env, s.l) - require.NoError(s.conf.T, err, "Connecting to blockchain nodes shouldn't fail") - - s.ContractDeployer, err = contracts.NewContractDeployer(s.EVMClient, s.l) - require.NoError(s.conf.T, err) - - s.ChainlinkNodes, err = client.ConnectChainlinkNodes(s.conf.Env) - require.NoError(s.conf.T, err, "Connecting to chainlink nodes shouldn't fail") - - s.Mockserver, err = ctfClient.ConnectMockServer(s.conf.Env) - require.NoError(s.conf.T, err, "Creating mockserver clients shouldn't fail") - - s.EVMClient.ParallelTransactions(true) - - s.LinkTokenContract, err = s.ContractDeployer.DeployLinkTokenContract() - require.NoError(s.conf.T, err, "Deploying Link Token Contract shouldn't fail") -} diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 18c12d35c92..81f2ce0edf4 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -33,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -195,7 +194,7 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.Keep if inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_0 || inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_1 || inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_2 { nodesToFund = k.chainlinkNodes[1:] } - err = actions_seth.FundChainlinkNodesAtKeyIndexFromRootAddress(k.log, k.chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(nodesToFund), k.Inputs.ChainlinkNodeFunding, index) + err = actions.FundChainlinkNodesAtKeyIndexFromRootAddress(k.log, k.chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(nodesToFund), k.Inputs.ChainlinkNodeFunding, index) require.NoError(k.t, err, "Funding Chainlink nodes shouldn't fail") } @@ -730,7 +729,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { registrar, err = contracts.DeployKeeperRegistrar(k.chainClient, registryVersion, k.linkToken.Address(), registrarSettings) require.NoError(k.t, err, "Funding keeper registrar contract shouldn't fail") } else { // OCR automation - v2.X - registry, registrar = actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar = actions.DeployAutoOCRRegistryAndRegistrar( k.t, k.chainClient, registryVersion, *k.Inputs.KeeperRegistrySettings, k.linkToken, ) @@ -799,10 +798,10 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { linkFunds = big.NewInt(0).Add(linkFunds, minLinkBalance) - err = actions_seth.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) + err = actions.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") - upkeepIds := actions_seth.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false) + upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false) k.keeperRegistries[index] = registry k.keeperRegistrars[index] = registrar diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index fcff17874ec..bcad989e171 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -15,6 +15,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -41,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -234,7 +235,7 @@ func (o *OCRSoakTest) Environment() *environment.Environment { } func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { - seth, err := actions_seth.GetChainClient(o.Config, o.rpcNetwork) + seth, err := seth_utils.GetChainClient(o.Config, o.rpcNetwork) require.NoError(o.t, err, "Error creating seth client") o.seth = seth @@ -249,14 +250,14 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { // Fund Chainlink nodes, excluding the bootstrap node o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(o.log, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) + err = actions.FundChainlinkNodesFromRootAddress(o.log, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) require.NoError(o.t, err, "Error funding Chainlink nodes") var forwarders []common.Address if o.OperatorForwarderFlow { var operators []common.Address - operators, forwarders, _ = actions_seth.DeployForwarderContracts( + operators, forwarders, _ = actions.DeployForwarderContracts( o.t, o.seth, common.HexToAddress(linkContract.Address()), len(o.workerNodes), ) require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") @@ -264,15 +265,15 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") for i := range o.workerNodes { - actions_seth.AcceptAuthorizedReceiversOperator( + actions.AcceptAuthorizedReceiversOperator( o.t, o.log, o.seth, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions_seth.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) + actions.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) } } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "1" { if o.OperatorForwarderFlow { - o.ocrV1Instances, err = actions_seth.DeployOCRContractsForwarderFlow( + o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( o.log, o.seth, *o.Config.OCR.Soak.NumberOfContracts, @@ -282,7 +283,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { ) require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") } else { - o.ocrV1Instances, err = actions_seth.DeployOCRv1Contracts( + o.ocrV1Instances, err = actions.DeployOCRv1Contracts( o.log, seth, *o.Config.OCR.Soak.NumberOfContracts, @@ -307,7 +308,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions_seth.DeployOCRv2Contracts( + o.ocrV2Instances, err = actions.DeployOCRv2Contracts( o.log, o.seth, *ocrTestConfig.GetOCRConfig().Soak.NumberOfContracts, @@ -318,7 +319,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { require.NoError(o.t, err, "Error deploying OCRv2 contracts") contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) require.NoError(o.t, err, "Error building median config") - err = actions_seth.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") } diff --git a/integration-tests/testsetups/profile.go b/integration-tests/testsetups/profile.go deleted file mode 100644 index 14fe3d29ae6..00000000000 --- a/integration-tests/testsetups/profile.go +++ /dev/null @@ -1,76 +0,0 @@ -package testsetups - -//revive:disable:dot-imports -import ( - "time" - - . "github.com/onsi/gomega" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" -) - -// ChainlinkProfileTest runs a piece of code on Chainlink nodes with PPROF enabled, then downloads the PPROF results -type ChainlinkProfileTest struct { - Inputs ChainlinkProfileTestInputs - TestReporter testreporters.ChainlinkProfileTestReporter - env *environment.Environment - c blockchain.EVMClient -} - -// ChainlinkProfileTestInputs are the inputs necessary to run a profiling tests -type ChainlinkProfileTestInputs struct { - ProfileFunction func(*client.ChainlinkClient) - ProfileDuration time.Duration - ChainlinkNodes []*client.ChainlinkK8sClient -} - -// NewChainlinkProfileTest prepares a new keeper Chainlink profiling test to be run -func NewChainlinkProfileTest(inputs ChainlinkProfileTestInputs) *ChainlinkProfileTest { - return &ChainlinkProfileTest{ - Inputs: inputs, - } -} - -// Setup prepares contracts for the test -func (c *ChainlinkProfileTest) Setup(env *environment.Environment) { - c.ensureInputValues() - c.env = env -} - -// Run runs the profiling test -func (c *ChainlinkProfileTest) Run() { - profileGroup := new(errgroup.Group) - for ni, cl := range c.Inputs.ChainlinkNodes { - chainlinkNode := cl - nodeIndex := ni - profileGroup.Go(func() error { - profileResults, err := chainlinkNode.Profile(c.Inputs.ProfileDuration, c.Inputs.ProfileFunction) - profileResults.NodeIndex = nodeIndex - if err != nil { - return err - } - c.TestReporter.Results = append(c.TestReporter.Results, profileResults) - return nil - }) - } - Expect(profileGroup.Wait()).ShouldNot(HaveOccurred(), "Error while gathering chainlink Profile tests") -} - -// Networks returns the networks that the test is running on -func (c *ChainlinkProfileTest) TearDownVals() (*environment.Environment, []*client.ChainlinkK8sClient, reportModel.TestReporter, blockchain.EVMClient) { - return c.env, c.Inputs.ChainlinkNodes, &c.TestReporter, c.c -} - -// ensureValues ensures that all values needed to run the test are present -func (c *ChainlinkProfileTest) ensureInputValues() { - Expect(c.Inputs.ProfileFunction).ShouldNot(BeNil(), "Forgot to provide a function to profile") - Expect(c.Inputs.ProfileDuration.Seconds()).Should(BeNumerically(">=", 1), "Time to profile should be at least 1 second") - Expect(c.Inputs.ChainlinkNodes).ShouldNot(BeNil(), "Chainlink nodes you want to profile should be provided") - Expect(len(c.Inputs.ChainlinkNodes)).Should(BeNumerically(">", 0), "No Chainlink nodes provided to profile") -} diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 9de11c439c8..7bedef393df 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -13,6 +13,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -31,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -981,7 +982,7 @@ type ChaosPauseData struct { } // ExecuteChaosExperiment executes the configured chaos experiment, which consist of pausing CL node or Postgres containers -func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, testConfig *tc.TestConfig, errorCh chan error) { +func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, sethClient *seth.Client, testConfig *tc.TestConfig, errorCh chan error) { if testConfig == nil || testConfig.LogPoller.ChaosConfig == nil || *testConfig.LogPoller.ChaosConfig.ExperimentCount == 0 { errorCh <- nil return @@ -990,12 +991,6 @@ func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv chaosChan := make(chan ChaosPauseData, *testConfig.LogPoller.ChaosConfig.ExperimentCount) wg := &sync.WaitGroup{} - selectedNetwork := networks.MustGetSelectedNetworkConfig(testConfig.Network)[0] - sethClient, err := testEnv.GetSethClient(selectedNetwork.ChainID) - if err != nil { - errorCh <- err - } - go func() { // if we wanted to have more than 1 container paused, we'd need to make sure we aren't trying to pause an already paused one guardChan := make(chan struct{}, 1) @@ -1119,37 +1114,26 @@ func SetupLogPollerTestDocker( WithTestInstance(t). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(chainlinkNodeFunding)). WithEVMNetworkOptions(evmNetworkExtraSettingsFn). WithChainlinkNodeLogScanner(logScannerSettings). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") - selectedNetwork := networks.MustGetSelectedNetworkConfig(testConfig.Network)[0] - chainClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + chainClient, err := seth_utils.GetChainClient(testConfig, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(chainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + nodeClients := env.ClCluster.NodeAPIs() workerNodes := nodeClients[1:] - var linkToken contracts.LinkToken - - switch network.ChainID { - // Simulated - case 1337: - linkToken, err = contracts.DeployLinkTokenContract(l, chainClient) - // Ethereum Sepolia - case 11155111: - linkToken, err = env.ContractLoader.LoadLINKToken("0x779877A7B0D9E8603169DdbD7836e478b4624789") - // Polygon Mumbai - case 80001: - linkToken, err = env.ContractLoader.LoadLINKToken("0x326C977E6efc84E512bB9C30f76E30c160eD06FB") - default: - panic("Not implemented") - } - require.NoError(t, err, "Error loading/deploying LINK token") + linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) + require.NoError(t, err, "Error deploying LINK token") linkBalance, err := linkToken.BalanceOf(context.Background(), chainClient.MustGetRootKeyAddress().Hex()) require.NoError(t, err, "Error getting LINK balance") @@ -1161,7 +1145,7 @@ func SetupLogPollerTestDocker( require.FailNowf(t, "Not enough LINK", "Not enough LINK to run the test. Need at least %s. but has only %s", big.NewInt(0).Div(minLinkBalance, big.NewInt(1e18)).String(), big.NewInt(0).Div(linkBalance, big.NewInt(1e18)).String()) } - registry, registrar := actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, chainClient, registryVersion,