From 11844e914335522a98fbcb738502f2ce8c13ca5a Mon Sep 17 00:00:00 2001 From: lei shi Date: Fri, 21 Jun 2024 12:24:33 +0800 Subject: [PATCH] rebase and polish --- .changeset/honest-avocados-heal.md | 5 + contracts/.changeset/green-pigs-reflect.md | 5 + .../native_solc_compile_all_automation | 2 +- .../actions/automationv2/actions.go | 53 +- .../contracts/contract_models.go | 1 - .../contracts/ethereum_contracts.go | 3124 ++++++----------- .../ethereum_contracts_automation.go | 152 +- .../contracts/ethereum_keeper_contracts.go | 2220 +----------- integration-tests/go.mod | 9 +- integration-tests/go.sum | 10 +- 10 files changed, 1251 insertions(+), 4330 deletions(-) create mode 100644 .changeset/honest-avocados-heal.md create mode 100644 contracts/.changeset/green-pigs-reflect.md diff --git a/.changeset/honest-avocados-heal.md b/.changeset/honest-avocados-heal.md new file mode 100644 index 00000000000..a28c08fde84 --- /dev/null +++ b/.changeset/honest-avocados-heal.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add test for v23 #added diff --git a/contracts/.changeset/green-pigs-reflect.md b/contracts/.changeset/green-pigs-reflect.md new file mode 100644 index 00000000000..cb197a32bcf --- /dev/null +++ b/contracts/.changeset/green-pigs-reflect.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add test for v23 #added diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation index dc75d18e4cb..f144e4f7dc8 100755 --- a/contracts/scripts/native_solc_compile_all_automation +++ b/contracts/scripts/native_solc_compile_all_automation @@ -12,7 +12,7 @@ OPTIMIZE_RUNS=1000000 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" -python3 -m pip install --require-hashes --break-system-packages -r "$SCRIPTPATH"/requirements.txt +python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt solc-select install $SOLC_VERSION solc-select use $SOLC_VERSION diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 1ba0a0eee5f..f0f625064b3 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -56,16 +56,14 @@ type NodeDetails struct { OCR2Id string } -// TODO add wrapped native address etc type AutomationTest struct { ChainClient *seth.Client - LinkToken contracts.LinkToken - //WETHToken contracts.WETHToken + LinkToken contracts.LinkToken Transcoder contracts.UpkeepTranscoder EthLinkFeed contracts.MockETHLINKFeed - EthUSDFeed contracts.MockETHUSDFeed // TODO new add - WETHToken contracts.WETHToken // TODO new add + EthUSDFeed contracts.MockETHUSDFeed + WETHToken contracts.WETHToken GasFeed contracts.MockGasFeed Registry contracts.KeeperRegistry Registrar contracts.KeeperRegistrar @@ -182,8 +180,6 @@ func (a *AutomationTest) LoadLINK(address string) error { return nil } -// TODO deploy WETH Token - func (a *AutomationTest) DeployTranscoder() error { transcoder, err := contracts.DeployUpkeepTranscoder(a.ChainClient) if err != nil { @@ -221,7 +217,7 @@ func (a *AutomationTest) LoadEthLinkFeed(address string) error { } func (a *AutomationTest) DeployEthUSDFeed() error { - // TODO change the fallback price, just hardcode it should be fine + // FallbackLinkPrice and FallbackETHPrice are the same ethUSDFeed, err := contracts.DeployMockETHUSDFeed(a.ChainClient, a.RegistrySettings.FallbackLinkPrice) if err != nil { return err @@ -239,7 +235,6 @@ func (a *AutomationTest) LoadEthUSDFeed(address string) error { return nil } -// var linkToken *contracts.EthereumLinkToken func (a *AutomationTest) DeployWETH() error { wethToken, err := contracts.DeployWETHTokenContract(a.Logger, a.ChainClient) if err != nil { @@ -277,11 +272,9 @@ func (a *AutomationTest) LoadEthGasFeed(address string) error { } func (a *AutomationTest) DeployRegistry() error { - // TODO add wrapped native address etc registryOpts := &contracts.KeeperRegistryOpts{ - RegistryVersion: a.RegistrySettings.RegistryVersion, - LinkAddr: a.LinkToken.Address(), - //WETHAddr: a.WETHToken.Address(), + RegistryVersion: a.RegistrySettings.RegistryVersion, + LinkAddr: a.LinkToken.Address(), ETHFeedAddr: a.EthLinkFeed.Address(), GasFeedAddr: a.GasFeed.Address(), TranscoderAddr: a.Transcoder.Address(), @@ -291,7 +284,6 @@ func (a *AutomationTest) DeployRegistry() error { NativeUSDFeedAddr: a.EthUSDFeed.Address(), WrappedNativeAddr: a.WETHToken.Address(), } - a.Logger.Info().Msgf("========hello = actions, %v, %v, %v", a.RegistrySettings.RegistryVersion, registryOpts.LinkUSDFeedAddr, registryOpts.WrappedNativeAddr) registry, err := contracts.DeployKeeperRegistry(a.ChainClient, registryOpts) if err != nil { return err @@ -413,10 +405,6 @@ func (a *AutomationTest) AddBootstrapJob() error { func (a *AutomationTest) AddAutomationJobs() error { var contractVersion string - // TODO what is the diff btw v2.1+ and v2.3 - //if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { - // contractVersion = "v2.3" - //} else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_2 || a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { contractVersion = "v2.1+" } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_1 { @@ -576,43 +564,20 @@ func (a *AutomationTest) SetConfigOnRegistry() error { } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { ocrConfig.TypedOnchainConfig23 = a.RegistrySettings.Create23OnchainConfig(a.Registrar.Address(), a.UpkeepPrivilegeManager, a.Registry.ChainModuleAddress(), a.Registry.ReorgProtectionEnabled()) ocrConfig.BillingTokens = []common.Address{ - common.HexToAddress(a.LinkToken.Address()), + common.HexToAddress(a.LinkToken.Address()), // TODO add more billing tokens } ocrConfig.BillingConfigs = []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig{ { GasFeePPB: 100, FlatFeeMilliCents: big.NewInt(500), - PriceFeed: common.HexToAddress(a.EthUSDFeed.Address()), + PriceFeed: common.HexToAddress(a.EthUSDFeed.Address()), // ETH/USD feed and LINK/USD feed are the same Decimals: 18, FallbackPrice: big.NewInt(1000), MinSpend: big.NewInt(200), }, } } - //function setConfigTypeSafe( - // address[] memory signers, - // address[] memory transmitters, - // uint8 f, - // OnchainConfig memory onchainConfig, // No this - // uint64 offchainConfigVersion, - // bytes memory offchainConfig, - // IERC20[] memory billingTokens, // not this - // BillingConfig[] memory billingConfigs // not this - //) - - //ocrConfig := contracts.OCRv2Config{ - // Signers: signers, - // Transmitters: transmitters, - // F: f, - // OffchainConfigVersion: offchainConfigVersion, - // OffchainConfig: offchainConfig, - //} - - // TODO log here to see what is ocrConfig - a.Logger.Info().Msgf("=====ocrConfig.BillingTokens: %v", ocrConfig.BillingTokens) - a.Logger.Info().Msgf("=====ocrConfig.BillingConfigs: %v", ocrConfig.BillingConfigs) - a.Logger.Info().Msgf("=====ocrConfig: %v", ocrConfig) err = a.Registry.SetConfigTypeSafe(ocrConfig) if err != nil { return errors.Join(err, fmt.Errorf("failed to set config on registry")) @@ -895,7 +860,6 @@ func (a *AutomationTest) SetupAutomationDeployment(t *testing.T) { err = a.DeployEthUSDFeed() require.NoError(t, err, "Error deploying eth usd feed contract") - // TODO deploy more err = a.DeployTranscoder() require.NoError(t, err, "Error deploying transcoder contract") @@ -905,7 +869,6 @@ func (a *AutomationTest) SetupAutomationDeployment(t *testing.T) { err = a.DeployRegistrar() require.NoError(t, err, "Error deploying registrar contract") - l.Info().Msgf("===================version in actions.go in SetupAutomationDeployment: %v", a.RegistrySettings.RegistryVersion) a.AddJobsAndSetConfig(t) } diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go index 94b07b19ab8..e221f3effb0 100644 --- a/integration-tests/contracts/contract_models.go +++ b/integration-tests/contracts/contract_models.go @@ -73,7 +73,6 @@ type FluxAggregator interface { WatchSubmissionReceived(ctx context.Context, eventChan chan<- *SubmissionEvent) error } -// TODO add Decimals type LinkToken interface { Address() string Approve(to string, amount *big.Int) error diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index 2310b4cf1ff..f6358c4da84 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -3,6 +3,7 @@ package contracts import ( "context" "encoding/hex" + "errors" "fmt" "math/big" "strings" @@ -11,2116 +12,1381 @@ import ( "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/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper" "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) +// 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 + TypedOnchainConfig23 i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig + OffchainConfigVersion uint64 + OffchainConfig []byte + BillingTokens []common.Address + BillingConfigs []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig } -// LegacyEthereumAPIConsumer API consumer for job type "directrequest" tests -type LegacyEthereumAPIConsumer struct { - address *common.Address - client blockchain.EVMClient - consumer *test_api_consumer_wrapper.TestAPIConsumer +type EthereumFunctionsLoadStats struct { + LastRequestID string + LastResponse string + LastError string + Total uint32 + Succeeded uint32 + Errored uint32 + Empty uint32 } -func (e *LegacyEthereumAPIConsumer) Address() string { - return e.address.Hex() +func Bytes32ToSlice(a [32]byte) (r []byte) { + r = append(r, a[:]...) + return } -func (e *LegacyEthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, +// 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 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 +func ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkK8sClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - 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 + return nodesAsInterface } -// 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 +func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - 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() + return nodesAsInterface } -// 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 +func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { + var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) + for i, contract := range contracts { + contractsAsInterface[i] = contract } - 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) + return contractsAsInterface } -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 +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 *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) + return contractsAsInterface } -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 +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 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) + return contractABI, err } -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 +// 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 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() +// EthereumOffchainAggregator represents the offchain aggregation contract +type EthereumOffchainAggregator struct { + client *seth.Client + ocr *offchainaggregator.OffchainAggregator + address *common.Address + l zerolog.Logger } -func (f *EthereumFunctionsOracleEventsMock) OracleResponse(requestId [32]byte) error { - opts, err := f.client.TransactionOpts(f.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 - } - tx, err := f.eventsMock.EmitOracleResponse(opts, requestId) - if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return f.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("OffChainAggregator", *abi) + seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) -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) + 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 f.client.ProcessTransaction(tx) -} -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 - } - return f.client.ProcessTransaction(tx) + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &contractAddress, + l: l, + }, nil } -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) +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 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() -} - -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) + 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 err + return EthereumOffchainAggregator{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - 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()) + ocr, err := offchainaggregator.NewOffchainAggregator(ocrDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err - } - tx, err := f.eventsMock.EmitBillingStart(opts, requestId, commitment) - if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &ocrDeploymentData.Address, + l: l, + }, nil } -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 +// 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)) } - tx, err := f.eventsMock.EmitBillingEnd(opts, requestId, subscriptionId, signerPayment, transmitterPayment, totalCost, success) - if err != nil { - return err + for _, p := range payees { + payeesAddr = append(payeesAddr, common.HexToAddress(p)) } - 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() -} + o.l.Info(). + Str("Transmitters", fmt.Sprintf("%v", transmitters)). + Str("Payees", fmt.Sprintf("%v", payees)). + Str("OCR Address", o.Address()). + Msg("Setting OCR Payees") -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) + _, err := o.client.Decode(o.ocr.SetPayees(o.client.NewTXOpts(), transmittersAddr, payeesAddr)) + return err } -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 - } - 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) -} - -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) -} +// 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] -// 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 -} + // 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 + } -func (f *LegacyEthereumKeeperRegistrar12Mock) Address() string { - return f.address.Hex() -} + // https://stackoverflow.com/questions/8032170/how-to-assign-string-to-bytes-array + copy(onChainSigningAddress[:], common.HexToAddress(primaryOCRKey.Attributes.OnChainSigningAddress).Bytes()) + copy(configPublicKey[:], decodeConfigKey) -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) -} + oracleIdentity := ocrConfigHelper.OracleIdentity{ + TransmitAddress: transmitters[i], + OnChainSigningAddress: onChainSigningAddress, + PeerID: primaryP2PKey.Attributes.PeerID, + OffchainPublicKey: offchainSigningAddress, + } + oracleIdentityExtra := ocrConfigHelper.OracleIdentityExtra{ + OracleIdentity: oracleIdentity, + SharedSecretEncryptionPublicKey: ocrTypes.SharedSecretEncryptionPublicKey(configPublicKey), + } -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 + ocrConfig.OracleIdentities = append(ocrConfig.OracleIdentities, oracleIdentityExtra) } - 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) + 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 } - 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 + // 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 } -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) +// 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 } -// LegacyEthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract -type LegacyEthereumFunctionsV1EventsMock struct { - client blockchain.EVMClient - eventsMock *functions_v1_events_mock.FunctionsV1EventsMock - address *common.Address +// 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 (f *LegacyEthereumFunctionsV1EventsMock) Address() string { - return f.address.Hex() +func (o *EthereumOffchainAggregator) Address() string { + return o.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) +// 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 err + return nil, err } - return f.client.ProcessTransaction(tx) + + return &RoundData{ + RoundId: roundData.RoundId, + Answer: roundData.Answer, + AnsweredInRound: roundData.AnsweredInRound, + StartedAt: roundData.StartedAt, + UpdatedAt: roundData.UpdatedAt, + }, err } -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) +func (o *EthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := o.ocr.LatestRoundData(o.client.NewCallOpts()) if err != nil { - return err + return nil, err } - return f.client.ProcessTransaction(tx) + return data.UpdatedAt, nil } -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) +// 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 err + return nil, err } - return f.client.ProcessTransaction(tx) + + return &RoundData{ + RoundId: roundData.RoundId, + Answer: roundData.Answer, + AnsweredInRound: roundData.AnsweredInRound, + StartedAt: roundData.StartedAt, + UpdatedAt: roundData.UpdatedAt, + }, nil } -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) +// ParseEventAnswerUpdated parses the log for event AnswerUpdated +func (o *EthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { + return o.ocr.ParseAnswerUpdated(eventLog) } -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) +// LegacyEthereumOperatorFactory represents operator factory contract +type EthereumOperatorFactory struct { + address *common.Address + client *seth.Client + operatorFactory *operator_factory.OperatorFactory } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) +func DeployEthereumOperatorFactory(seth *seth.Client, linkTokenAddress common.Address) (EthereumOperatorFactory, error) { + abi, err := operator_factory.OperatorFactoryMetaData.GetAbi() if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("failed to get OperatorFactory ABI: %w", err) } - tx, err := f.eventsMock.EmitSubscriptionCreated(opts, subscriptionId, owner) + operatorData, err := seth.DeployContract(seth.NewTXOpts(), "OperatorFactory", *abi, common.FromHex(operator_factory.OperatorFactoryMetaData.Bin), linkTokenAddress) if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("OperatorFactory instance deployment have failed: %w", 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) + operatorFactory, err := operator_factory.NewOperatorFactory(operatorData.Address, seth.Client) if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("failed to instantiate OperatorFactory instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumOperatorFactory{ + address: &operatorData.Address, + client: seth, + operatorFactory: operatorFactory, + }, nil } -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 (e *EthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { + return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) } -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 (e *EthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { + return e.operatorFactory.ParseOperatorCreated(eventLog) } -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 (e *EthereumOperatorFactory) Address() string { + return e.address.Hex() +} + +func (e *EthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return e.operatorFactory.DeployNewOperatorAndForwarder(e.client.NewTXOpts()) } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) +// 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 } - tx, err := f.eventsMock.EmitContractUpdated(opts, id, from, to) + 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 err + return EthereumOperator{}, err } - return f.client.ProcessTransaction(tx) + + return EthereumOperator{ + address: &contractAddress, + client: seth, + operator: operator, + l: logger, + }, nil } -// LegacyEthereumFluxAggregator represents the basic flux aggregation contract -type LegacyEthereumFluxAggregator struct { - client blockchain.EVMClient - fluxAggregator *flux_aggregator_wrapper.FluxAggregator - address *common.Address +func (e *EthereumOperator) Address() string { + return e.address.Hex() } -func (f *LegacyEthereumFluxAggregator) Address() string { - return f.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 } -// 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) +// EthereumAuthorizedForwarder represents authorized forwarder contract +type EthereumAuthorizedForwarder struct { + address *common.Address + client *seth.Client + authorizedForwarder *authorized_forwarder.AuthorizedForwarder } -func (f *LegacyEthereumFluxAggregator) UpdateAvailableFunds() error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) +func LoadEthereumAuthorizedForwarder(seth *seth.Client, contractAddress common.Address) (EthereumAuthorizedForwarder, error) { + abi, err := authorized_forwarder.AuthorizedForwarderMetaData.GetAbi() if err != nil { - return err + return EthereumAuthorizedForwarder{}, err } - tx, err := f.fluxAggregator.UpdateAvailableFunds(opts) + 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 err + return EthereumAuthorizedForwarder{}, fmt.Errorf("failed to instantiate AuthorizedForwarder instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumAuthorizedForwarder{ + address: &contractAddress, + client: seth, + authorizedForwarder: authorizedForwarder, + }, nil } -func (f *LegacyEthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { +// 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: common.HexToAddress(f.client.GetDefaultWallet().Address()), + From: e.client.Addresses[0], Context: ctx, } - payment, err := f.fluxAggregator.PaymentAmount(opts) + authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) if err != nil { return nil, err } - return payment, nil + var sendersAddrs []string + for _, o := range authorizedSenders { + sendersAddrs = append(sendersAddrs, o.Hex()) + } + return sendersAddrs, 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) +func (e *EthereumAuthorizedForwarder) Address() string { + return e.address.Hex() } -// 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 - } - } +type EthereumOffchainAggregatorV2 struct { + address *common.Address + client *seth.Client + contract *ocr2aggregator.OCR2Aggregator + l zerolog.Logger } -func (f *LegacyEthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) +func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return err - } - tx, err := f.fluxAggregator.SetRequesterPermissions(opts, addr, authorized, roundsDelay) - if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return f.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) -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) + ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) if err != nil { - return nil, err - } - var oracleAddrs []string - for _, o := range addresses { - oracleAddrs = append(oracleAddrs, o.Hex()) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return oracleAddrs, nil + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &contractAddress, + l: l, + }, 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) +func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return nil, err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return rID, nil -} + 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, + ) -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 + return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - tx, err := f.fluxAggregator.WithdrawPayment(opts, from, to, amount) + + ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &ocrDeploymentData2.Address, + l: l, + }, nil } -func (f *LegacyEthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), +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, - } - 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()), +func (e *EthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { + data, err := e.contract.LatestRoundData(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - lr, err := f.fluxAggregator.LatestRoundData(opts) + }) if err != nil { - return flux_aggregator_wrapper.LatestRoundData{}, err + return nil, err } - return lr, nil + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, 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()), +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, - } - - allocated, err := f.fluxAggregator.AllocatedFunds(opts) + }, roundID) if err != nil { - return &FluxAggregatorData{}, err + return nil, err } + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, nil +} - available, err := f.fluxAggregator.AvailableFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } +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") - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return &FluxAggregatorData{}, err + var addTransmitters, addrPayees []common.Address + for _, t := range transmitters { + addTransmitters = append(addTransmitters, common.HexToAddress(t)) } - latestRound := RoundData(lr) - - oracles, err := f.fluxAggregator.GetOracles(opts) - if err != nil { - return &FluxAggregatorData{}, err + for _, p := range payees { + addrPayees = append(addrPayees, common.HexToAddress(p)) } - return &FluxAggregatorData{ - AllocatedFunds: allocated, - AvailableFunds: available, - LatestRoundData: latestRound, - Oracles: oracles, - }, nil + _, err := e.client.Decode(e.contract.SetPayees(e.client.NewTXOpts(), addTransmitters, addrPayees)) + return err } -// 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 - } +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") - 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) + _, err := e.client.Decode(e.contract.SetConfig( + e.client.NewTXOpts(), + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + )) + return err } -// 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) +func (e *EthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { + return e.contract.ParseAnswerUpdated(log) } -// 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 +// EthereumLinkToken represents a LinkToken address +type EthereumLinkToken struct { + client *seth.Client + instance *link_token_interface.LinkToken + address common.Address + 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, - } +func (l *EthereumLinkToken) Decimals() uint { + return 18 } -// 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 +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) } - lr, err := f.fluxInstance.LatestRoundID(context.Background()) + linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) if err != nil { - return err + return &EthereumLinkToken{}, fmt.Errorf("LinkToken instance deployment have failed: %w", 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) - } + + 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) } -} -func (f *FluxAggregatorRoundConfirmer) Complete() bool { - return f.complete + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: linkDeploymentData.Address, + l: l, + }, nil } -// LegacyEthereumLinkToken represents a LinkToken address -type LegacyEthereumLinkToken struct { - client blockchain.EVMClient - instance *link_token_interface.LinkToken - address common.Address - l zerolog.Logger -} +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) + } -// 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, - }) + 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 err + return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) } - return l.client.Fund(l.address.Hex(), ethAmount, gasEstimates) + + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: address, + l: l, + }, nil } -func (l *LegacyEthereumLinkToken) Decimals() uint { - return 18 +// 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") } -func (l *LegacyEthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().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, - } - balance, err := l.instance.BalanceOf(opts, common.HexToAddress(addr)) - if err != nil { - return nil, err - } - return balance, nil + }, common.HexToAddress(addr)) + } // 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, - } - return l.instance.Name(opts) +func (l *EthereumLinkToken) Name(ctx context.Context) (string, error) { + return l.instance.Name(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }) } -func (l *LegacyEthereumLinkToken) Address() string { +func (l *EthereumLinkToken) Address() string { return l.address.Hex() } -func (l *LegacyEthereumLinkToken) Approve(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return err - } +func (l *EthereumLinkToken) Approve(to string, amount *big.Int) error { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). 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) - if err != nil { - return err - } - return l.client.ProcessTransaction(tx) + _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (l *LegacyEthereumLinkToken) Transfer(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return err - } +func (l *EthereumLinkToken) Transfer(to string, amount *big.Int) error { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). 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) - if err != nil { - return err - } - return l.client.ProcessTransaction(tx) + _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (l *LegacyEthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := l.instance.TransferAndCall(opts, common.HexToAddress(to), amount, data) - if err != nil { - return nil, err - } +func (l *EthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). 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 -} - -// SetPayees sets wallets for the contract to pay out to? -func (o *LegacyEthereumOffchainAggregator) SetPayees( - transmitters, payees []string, -) error { - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) + decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXOpts(), common.HexToAddress(to), amount, data)) if err != nil { - return err - } - 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)) + return nil, err } + return decodedTx.Transaction, nil +} - o.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCR Address", o.Address()). - Msg("Setting OCR Payees") - - tx, err := o.ocr.SetPayees(opts, transmittersAddr, payeesAddr) +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 err + return nil, err } - return o.client.ProcessTransaction(tx) + return decodedTx.Transaction, nil } -// SetConfig sets the payees and the offchain reporting protocol configuration -func (o *LegacyEthereumOffchainAggregator) 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) +// 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)) - 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, + 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 err - } - // Set Config - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) if err != nil { - return err + return &EthereumFluxAggregator{}, fmt.Errorf("FluxAggregator instance deployment have failed: %w", err) } - tx, err := o.ocr.SetConfig(opts, signers, transmitters, threshold, encodedConfigVersion, encodedConfig) + + 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 o.client.ProcessTransaction(tx) + + return &EthereumFluxAggregator{ + client: seth, + address: &fluxDeploymentData.Address, + fluxAggregator: flux, + }, nil } -// 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 - } - o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") +// EthereumFluxAggregator represents the basic flux aggregation contract +type EthereumFluxAggregator struct { + client *seth.Client + fluxAggregator *flux_aggregator_wrapper.FluxAggregator + address *common.Address +} - return o.client.ProcessTransaction(tx) +func (f *EthereumFluxAggregator) Address() string { + return f.address.Hex() } -// 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) +// 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 (o *LegacyEthereumOffchainAggregator) Address() string { - return o.address.Hex() +func (f *EthereumFluxAggregator) UpdateAvailableFunds() error { + _, err := f.client.Decode(f.fluxAggregator.UpdateAvailableFunds(f.client.NewTXOpts())) + return err } -// 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 (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.PaymentAmount(&bind.CallOpts{ + From: f.client.Addresses[0], Context: ctx, - } + }) +} - roundData, err := o.ocr.LatestRoundData(opts) - if err != nil { - return nil, err - } +func (f *EthereumFluxAggregator) RequestNewRound(context.Context) error { + _, err := f.client.Decode(f.fluxAggregator.RequestNewRound(f.client.NewTXOpts())) + return err +} - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, 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 (o *LegacyEthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := o.ocr.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil +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 } -// 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 (f *EthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { + addresses, err := f.fluxAggregator.GetOracles(&bind.CallOpts{ + From: f.client.Addresses[0], Context: ctx, - } - roundData, err := o.ocr.GetRoundData(opts, 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 *LegacyEthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { - return o.ocr.ParseAnswerUpdated(eventLog) + var oracleAddrs []string + for _, o := range addresses { + oracleAddrs = append(oracleAddrs, o.Hex()) + } + return oracleAddrs, nil } -// 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 +func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.LatestRound(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -// 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 (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 } -// 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()) - if err != nil { - return 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) - } - } +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) } -// 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 (f *EthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { + return f.fluxAggregator.LatestRoundData(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -// 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, +// 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, } -} -// 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 + allocated, err := f.fluxAggregator.AllocatedFunds(opts) + if err != nil { + return &FluxAggregatorData{}, err } - lr, err := o.ocrInstance.GetLatestRound(context.Background()) + available, err := f.fluxAggregator.AvailableFunds(opts) if err != nil { - return 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 &FluxAggregatorData{}, err } -} - -func (o *OffchainAggregatorRoundConfirmer) Complete() bool { - return o.complete -} - -// 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 -} -// 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, + lr, err := f.fluxAggregator.LatestRoundData(opts) + if err != nil { + return &FluxAggregatorData{}, err } -} + latestRound := RoundData(lr) -// 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 + oracles, err := f.fluxAggregator.GetOracles(opts) + if err != nil { + return &FluxAggregatorData{}, err } - lr, err := o.ocrInstance.GetLatestRound(context.Background()) + 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 } - 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) - } - } + return err } -func (o *OffchainAggregatorV2RoundConfirmer) Complete() bool { - return o.complete +// 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, + }) } -// LegacyEthereumMockETHLINKFeed represents mocked ETH/LINK feed contract -type LegacyEthereumMockETHLINKFeed struct { - client blockchain.EVMClient - feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator - address *common.Address -} +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)) -func (v *LegacyEthereumMockETHLINKFeed) Address() string { - return v.address.Hex() -} + oracleDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "Oracle", *abi, common.FromHex(oracle_wrapper.OracleMetaData.Bin), + common.HexToAddress(linkAddr), + ) -func (v *LegacyEthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) if err != nil { - return nil, err + return &EthereumOracle{}, fmt.Errorf("Oracle instance deployment have failed: %w", err) } - return data.Ans, 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(), - }) + oracle, err := oracle_wrapper.NewOracle(oracleDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return nil, err + return &EthereumOracle{}, fmt.Errorf("Oracle to instantiate FluxAggregator 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 -} -func (v *LegacyEthereumMockGASFeed) Address() string { - return v.address.Hex() + return &EthereumOracle{ + client: seth, + address: &oracleDeploymentData.Address, + oracle: oracle, + }, nil } -// EthereumFlags represents flags contract -type EthereumFlags struct { - client blockchain.EVMClient - flags *flags_wrapper.Flags +// EthereumOracle oracle for "directrequest" job tests +type EthereumOracle struct { address *common.Address + client *seth.Client + oracle *oracle_wrapper.Oracle } -func (e *EthereumFlags) Address() string { +func (e *EthereumOracle) 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()), - 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 *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 *LegacyEthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { - return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) +// 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 *LegacyEthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { - return e.operatorFactory.ParseOperatorCreated(eventLog) -} +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)) -func (e *LegacyEthereumOperatorFactory) Address() string { - return e.address.Hex() -} + consumerDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "TestAPIConsumer", *abi, common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin), + common.HexToAddress(linkAddr), + ) -func (e *LegacyEthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { - return nil, err + return &EthereumAPIConsumer{}, fmt.Errorf("TestAPIConsumer instance deployment have failed: %w", err) } - tx, err := e.operatorFactory.DeployNewOperatorAndForwarder(opts) + + consumer, err := test_api_consumer_wrapper.NewTestAPIConsumer(consumerDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return nil, err + return &EthereumAPIConsumer{}, fmt.Errorf("failed to instantiate TestAPIConsumer instance: %w", err) } - return tx, 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 -} -func (e *LegacyEthereumOperator) Address() string { - return e.address.Hex() + return &EthereumAPIConsumer{ + client: seth, + address: &consumerDeploymentData.Address, + consumer: consumer, + }, nil } -func (e *LegacyEthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return 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) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +// EthereumAPIConsumer API consumer for job type "directrequest" tests +type EthereumAPIConsumer struct { + address *common.Address + client *seth.Client + consumer *test_api_consumer_wrapper.TestAPIConsumer } -// 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 +func (e *EthereumAPIConsumer) Address() string { + return e.address.Hex() } -// 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()), +func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { + return e.consumer.CurrentRoundID(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - owner, err := e.authorizedForwarder.Owner(opts) + }) +} - return owner.Hex(), err +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") } -func (e *LegacyEthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +func (e *EthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { + return e.consumer.Data(&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 *LegacyEthereumAuthorizedForwarder) 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 } -// EthereumMockAggregatorProxy represents mock aggregator proxy contract -type EthereumMockAggregatorProxy struct { - address *common.Address - client blockchain.EVMClient - mockAggregatorProxy *mock_aggregator_proxy.MockAggregatorProxy +// EthereumMockETHLINKFeed represents mocked ETH/LINK feed contract +type EthereumMockETHLINKFeed struct { + client *seth.Client + feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator + address *common.Address } -func (e *EthereumMockAggregatorProxy) Address() string { - return e.address.Hex() +func (v *EthereumMockETHLINKFeed) Address() string { + return v.address.Hex() } -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) +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 err + return nil, err } - return e.client.ProcessTransaction(tx) + return data.Ans, nil } -func (e *EthereumMockAggregatorProxy) Aggregator() (common.Address, error) { - addr, err := e.mockAggregatorProxy.Aggregator(&bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +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 common.Address{}, err + return nil, err } - return addr, nil + return data.UpdatedAt, nil } -func channelClosed(ch <-chan struct{}) bool { - select { - case <-ch: - return true - default: +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) } - return false -} - -// 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 -} - -// 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 - TypedOnchainConfig23 i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig - OffchainConfigVersion uint64 - OffchainConfig []byte - BillingTokens []common.Address - BillingConfigs []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig -} + 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) + } -func (e *LegacyEthereumOffchainAggregatorV2) Address() string { - return e.address.Hex() + return &EthereumMockETHLINKFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) RequestNewRound() error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +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) } - tx, err := e.contract.RequestNewRound(opts) + 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 err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) } - return e.client.ProcessTransaction(tx) + + return &EthereumMockETHLINKFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - return e.contract.LatestAnswer(opts) +// EthereumMockGASFeed represents mocked Gas feed contract +type EthereumMockGASFeed struct { + client *seth.Client + feed *mock_gas_aggregator_wrapper.MockGASAggregator + address *common.Address } -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, +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 := e.contract.LatestRoundData(opts) + 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 &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, - } - data, err := e.contract.GetRoundData(opts, roundID) + 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 &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, + + return &EthereumMockGASFeed{ + address: &data.Address, + client: client, + feed: instance, }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func LoadMockGASFeed(client *seth.Client, address common.Address) (MockGasFeed, error) { + abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() 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") - - 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)) + 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)) - tx, err := e.contract.SetPayees(opts, addTransmitters, addrPayees) + instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) } - return e.client.ProcessTransaction(tx) + + return &EthereumMockGASFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) 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 err + return common.Address{}, 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, - ) + + data, err := client.DeployContract(client.NewTXOpts(), "MultiCall", abi, common.FromHex(MultiCallBIN)) if err != nil { - return err + return common.Address{}, fmt.Errorf("MultiCall instance deployment have failed: %w", err) } - return e.client.ProcessTransaction(tx) + + return data.Address, nil } -func (e *LegacyEthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { - return e.contract.ParseAnswerUpdated(log) +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 } -// EthereumKeeperRegistryCheckUpkeepGasUsageWrapper represents a gas wrapper for keeper registry -type EthereumKeeperRegistryCheckUpkeepGasUsageWrapper struct { - address *common.Address - client blockchain.EVMClient - gasUsageWrapper *gas_wrapper.KeeperRegistryCheckUpkeepGasUsageWrapper +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 *EthereumKeeperRegistryCheckUpkeepGasUsageWrapper) Address() string { +func (e *EthereumFunctionsCoordinator) Address() string { return e.address.Hex() } -/* Functions 1_0_0 */ +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 LegacyEthereumFunctionsRouter struct { +type EthereumFunctionsRouter struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *functions_router.FunctionsRouter l zerolog.Logger } -func (e *LegacyEthereumFunctionsRouter) Address() string { +func (e *EthereumFunctionsRouter) Address() string { return e.address.Hex() } -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)) +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 err := e.client.ProcessTransaction(tx); err != nil { - return 0, err - } - r, err := e.client.GetTxReceipt(tx.Hash()) - 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 r.Logs { + for _, l := range tx.Receipt.Logs { e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() } topicsMap := map[string]interface{}{} @@ -2133,7 +1399,7 @@ func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer 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]} + 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) } @@ -2144,63 +1410,61 @@ func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer return topicsMap["subscriptionId"].(uint64), nil } -type LegacyEthereumFunctionsCoordinator struct { - address common.Address - client blockchain.EVMClient - instance *functions_coordinator.FunctionsCoordinator -} +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) + } -func (e *LegacyEthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), + 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 e.instance.GetThresholdPublicKey(opts) + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: data.Address, + }, nil } -func (e *LegacyEthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), +// 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) } - return e.instance.GetDONPublicKey(opts) -} + seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) + seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) -func (e *LegacyEthereumFunctionsCoordinator) Address() string { - return e.address.Hex() + 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 LegacyEthereumFunctionsLoadTestClient struct { +type EthereumFunctionsLoadTestClient struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *functions_load_test_client.FunctionsLoadTestClient } -func (e *LegacyEthereumFunctionsLoadTestClient) Address() string { +func (e *EthereumFunctionsLoadTestClient) Address() string { return e.address.Hex() } -type EthereumFunctionsLoadStats struct { - LastRequestID string - LastResponse string - LastError string - Total uint32 - Succeeded uint32 - Errored uint32 - Empty uint32 -} - -func Bytes32ToSlice(a [32]byte) (r []byte) { - r = append(r, a[:]...) - return -} - -func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), - } - lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(opts) +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 } @@ -2215,341 +1479,199 @@ func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLo }, 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) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (e *EthereumFunctionsLoadTestClient) ResetStats() error { + _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) + return err } -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()) - if err != nil { - return err - } - tx, err := e.instance.SendRequest(opts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +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 *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) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +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 } -type EthereumMercuryVerifier struct { +// EthereumWETHToken represents a WETH address +type EthereumWETHToken struct { + client *seth.Client + instance *weth9_wrapper.WETH9 address common.Address - client blockchain.EVMClient - instance *verifier.Verifier l zerolog.Logger } -func (e *EthereumMercuryVerifier) Address() common.Address { - return e.address -} - -func (e *EthereumMercuryVerifier) Verify(signedReport []byte, sender common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployWETHTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumWETHToken, error) { + wethTokenAbi, err := weth9_wrapper.WETH9MetaData.GetAbi() if err != nil { - return err + return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err) } - tx, err := e.instance.Verify(opts, signedReport, sender) + wethDeploymentData, err := client.DeployContract(client.NewTXOpts(), "WETHToken", *wethTokenAbi, common.FromHex(weth9_wrapper.WETH9MetaData.Bin)) if err != nil { - return err + return &EthereumWETHToken{}, fmt.Errorf("WETH token instance deployment failed: %w", err) } - return e.client.ProcessTransaction(tx) -} -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()") + wethToken, err := weth9_wrapper.NewWETH9(wethDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumWETHToken{ + client: client, + instance: wethToken, + address: wethDeploymentData.Address, + l: l, + }, nil } -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()") +func LoadWETHTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumWETHToken, error) { + abi, err := weth9_wrapper.WETH9MetaData.GetAbi() if err != nil { - return verifier.LatestConfigDetails{}, err + return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err) } - return d, nil -} - -type EthereumMercuryVerifierProxy struct { - address common.Address - client blockchain.EVMClient - instance *verifier_proxy.VerifierProxy - l zerolog.Logger -} -func (e *EthereumMercuryVerifierProxy) Address() common.Address { - return e.address -} + client.ContractStore.AddABI("WETHToken", *abi) + client.ContractStore.AddBIN("WETHToken", common.FromHex(weth9_wrapper.WETH9MetaData.Bin)) -func (e *EthereumMercuryVerifierProxy) InitializeVerifier(verifierAddress common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, 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()") + wethToken, err := weth9_wrapper.NewWETH9(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %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) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) + return &EthereumWETHToken{ + client: client, + instance: wethToken, + address: address, + l: l, + }, 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 - } - if err != nil { - return nil, err - } - tx, err := e.instance.VerifyBulk(opts, signedReports, parameterPayload) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +// Fund the WETH Token contract with ETH to distribute the token +func (l *EthereumWETHToken) Fund(_ *big.Float) error { + panic("do not use this function, use actions_seth.SendFunds instead") } -func (e *EthereumMercuryVerifierProxy) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called MercuryVerifierProxy.SetFeeManager()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (l *EthereumWETHToken) Decimals() uint { + return 18 } -type EthereumMercuryFeeManager struct { - address common.Address - client blockchain.EVMClient - instance *fee_manager.FeeManager - l zerolog.Logger -} +func (l *EthereumWETHToken) 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 *EthereumMercuryFeeManager) Address() common.Address { - return e.address } -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()) - if err != nil { - return nil, err - } - tx, err := e.instance.UpdateSubscriberDiscount(opts, subscriber, feedId, token, discount) - e.l.Info().Err(err).Msg("Called EthereumMercuryFeeManager.UpdateSubscriberDiscount()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +// Name returns the name of the weth token +func (l *EthereumWETHToken) Name(ctx context.Context) (string, error) { + return l.instance.Name(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }) } -type EthereumMercuryRewardManager struct { - address common.Address - client blockchain.EVMClient - instance *reward_manager.RewardManager - l zerolog.Logger +func (l *EthereumWETHToken) Address() string { + return l.address.Hex() } -func (e *EthereumMercuryRewardManager) Address() common.Address { - return e.address +func (l *EthereumWETHToken) 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 WETH Transfer") + _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (e *EthereumMercuryRewardManager) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called EthereumMercuryRewardManager.SetFeeManager()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (l *EthereumWETHToken) 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 WETH") + _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -type EthereumWERC20Mock struct { - address common.Address - client blockchain.EVMClient - instance *werc20_mock.WERC20Mock - l zerolog.Logger +// EthereumMockETHUSDFeed represents mocked ETH/USD feed contract +// For the integration tests, we also use this ETH/USD feed for LINK/USD feed since they have the same structure +type EthereumMockETHUSDFeed struct { + client *seth.Client + feed *mock_ethusd_aggregator_wrapper.MockETHUSDAggregator + address *common.Address } -func (e *EthereumWERC20Mock) Address() common.Address { - return e.address +func (l *EthereumMockETHUSDFeed) Decimals() uint { + return 8 } -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) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (v *EthereumMockETHUSDFeed) Address() string { + return v.address.Hex() } -func (e *EthereumWERC20Mock) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - balance, err := e.instance.BalanceOf(opts, common.HexToAddress(addr)) +func (v *EthereumMockETHUSDFeed) 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 balance, nil + return data.Ans, nil } -func (e *EthereumWERC20Mock) Transfer(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("EthereumWERC20Mock.Transfer()") - tx, err := e.instance.Transfer(opts, common.HexToAddress(to), amount) +func (v *EthereumMockETHUSDFeed) 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 *EthereumWERC20Mock) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMockETHUSDFeed(client *seth.Client, answer *big.Int) (MockETHUSDFeed, error) { + abi, err := mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to get MockETHUSDFeed 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 := client.DeployContract(client.NewTXOpts(), "MockETHUSDFeed", *abi, common.FromHex(mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.Bin), answer) if err != nil { - return tx, 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 - } - - return nodesAsInterface -} - -func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { - var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) - for i, node := range k8sNodes { - nodesAsInterface[i] = node + return &EthereumMockETHUSDFeed{}, fmt.Errorf("MockETHUSDFeed instance deployment have failed: %w", err) } - return nodesAsInterface -} - -func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract + instance, err := mock_ethusd_aggregator_wrapper.NewMockETHUSDAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to instantiate MockETHUSDFeed instance: %w", err) } - return contractsAsInterface + return &EthereumMockETHUSDFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func V1OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregator) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract +func LoadMockETHUSDFeed(client *seth.Client, address common.Address) (MockETHUSDFeed, error) { + abi, err := mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to get MockETHUSDFeed ABI: %w", err) } + client.ContractStore.AddABI("MockETHUSDFeed", *abi) + client.ContractStore.AddBIN("MockETHUSDFeed", common.FromHex(mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.Bin)) - return contractsAsInterface -} - -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() + instance, err := mock_ethusd_aggregator_wrapper.NewMockETHUSDAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to instantiate MockETHUSDFeed instance: %w", err) } - return contractABI, err + return &EthereumMockETHUSDFeed{ + address: &address, + client: client, + feed: instance, + }, nil } diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index 486f19e679f..4bd140ba297 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -190,8 +190,6 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error txOpts := v.client.NewTXOpts() var err error - v.l.Error().Msg("===============Setting config for registry") - //v.l.Info().Msgf("=======Setting config for registry %s", v.version) switch v.version { case ethereum.RegistryVersion_2_1: _, err = v.client.Decode(v.registry2_1.SetConfigTypeSafe(txOpts, @@ -212,7 +210,6 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error ocrConfig.OffchainConfig, )) case ethereum.RegistryVersion_2_3: - // TODO need to change to real LINK address _, err = v.client.Decode(v.registry2_3.SetConfigTypeSafe(txOpts, ocrConfig.Signers, ocrConfig.Transmitters, @@ -1409,7 +1406,6 @@ func deployRegistry23(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistryLogicC2_3 ABI: %w", err) } - // TODO update args logicCData, err := client.DeployContract(client.NewTXOpts(), "AutomationRegistryLogicC2_3", *logicCAbi, common.FromHex(registrylogicc23.AutomationRegistryLogicCMetaData.Bin), common.HexToAddress(opts.LinkAddr), common.HexToAddress(opts.LinkUSDFeedAddr), @@ -1417,7 +1413,7 @@ func deployRegistry23(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi common.HexToAddress(opts.GasFeedAddr), automationForwarderLogicAddr, allowedReadOnlyAddress, - uint8(0), + uint8(0), // onchain payout mode common.HexToAddress(opts.WrappedNativeAddr), ) if err != nil { @@ -1495,7 +1491,7 @@ func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Ad keeper, err = loadRegistry2_1(client, address) case eth_contracts.RegistryVersion_2_2: // why the contract name is not the same as the actual contract name? keeper, err = loadRegistry2_2(client, address) - case eth_contracts.RegistryVersion_2_3: // why the contract name is not the same as the actual contract name? + case eth_contracts.RegistryVersion_2_3: keeper, err = loadRegistry2_3(client, address) default: return nil, fmt.Errorf("keeper registry version %d is not supported", registryVersion) @@ -1831,89 +1827,57 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt ) return req, err } else if v.registrar23 != 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 := acutils.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 - // } - // - // // TODO update params - // 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 - //} - - //struct RegistrationParams { - // address upkeepContract; - // uint96 amount; - // // 1 word full - // address adminAddress; - // uint32 gasLimit; - // uint8 triggerType; - // // 7 bytes left in 2nd word - // IERC20 billingToken; - // // 12 bytes left in 3rd word - // string name; - // bytes encryptedEmail; - // bytes checkData; - // bytes triggerConfig; - // bytes offchainConfig; - //} - registrarABI = cltypes.MustGetABI(registrar23.AutomationRegistrarABI) - //type RegistrationParams struct { - // UpkeepContract common.Address - // Amount *big.Int - // AdminAddress common.Address - // GasLimit uint32 - // TriggerType uint8 - // BillingToken common.Address - // Name string - // EncryptedEmail []byte - // CheckData []byte - // TriggerConfig []byte - // OffchainConfig []byte - //} + 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 := acutils.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 + } + + params := registrar23.AutomationRegistrar23RegistrationParams{ + UpkeepContract: common.HexToAddress(upkeepAddr), + Amount: amount, + AdminAddress: common.HexToAddress(adminAddr), + GasLimit: gasLimit, + TriggerType: uint8(1), // trigger type + BillingToken: common.HexToAddress(linkTokenAddr), + Name: name, + EncryptedEmail: email, + CheckData: checkData, + TriggerConfig: encodedLogTriggerConfig, + OffchainConfig: []byte{}, + } + + req, err := registrarABI.Methods["registerUpkeep"].Inputs.Pack(¶ms) + return req, err + } params := registrar23.AutomationRegistrar23RegistrationParams{ UpkeepContract: common.HexToAddress(upkeepAddr), @@ -1929,11 +1893,6 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt OffchainConfig: []byte{}, } - //req, err := registrarABI.Pack( - // "registerUpkeep", - // params, - //) - encodedRegistrationParamsStruct, err := registrarABI.Methods["registerUpkeep"].Inputs.Pack(¶ms) return encodedRegistrationParamsStruct, err @@ -1960,7 +1919,6 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt return req, nil } -// TODO add registrar 23 func DeployKeeperRegistrar(client *seth.Client, registryVersion eth_contracts.KeeperRegistryVersion, linkAddr string, registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) { if registryVersion == eth_contracts.RegistryVersion_2_0 { abi, err := keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.GetAbi() @@ -2034,13 +1992,6 @@ func DeployKeeperRegistrar(client *seth.Client, registryVersion eth_contracts.Ke AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, } - //address LINKAddress, - // IAutomationRegistryMaster2_3 registry, - // InitialTriggerConfig[] memory triggerConfigs, - // IERC20[] memory billingTokens, - // uint256[] memory minRegistrationFees, - // IWrappedNative wrappedNativeToken - billingTokens := []common.Address{ common.HexToAddress(linkAddr), } @@ -2048,7 +1999,6 @@ func DeployKeeperRegistrar(client *seth.Client, registryVersion eth_contracts.Ke big.NewInt(10), } - // TODO update params data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistrar2_3", *abi, common.FromHex(registrar23.AutomationRegistrarMetaData.Bin), common.HexToAddress(linkAddr), common.HexToAddress(registrarSettings.RegistryAddr), diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 41bfbebf697..b8a0e37f02f 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -2,50 +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/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" 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) @@ -184,77 +153,6 @@ type KeeperRegistrySettings struct { RegistryVersion ethereum.KeeperRegistryVersion } -// KeeperRegistrarSettings represents settings for registrar contract -type KeeperRegistrarSettings struct { - AutoApproveConfigType uint8 - AutoApproveMaxAllowed uint16 - RegistryAddr string - MinLinkJuels *big.Int - WETHTokenAddr string -} - -// 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) Create23OnchainConfig(registrar string, registryOwnerAddress, chainModuleAddress common.Address, reorgProtectionEnabled bool) i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig { return i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig{ CheckGasLimit: rcs.CheckGasLimit, @@ -276,6 +174,26 @@ func (rcs *KeeperRegistrySettings) Create23OnchainConfig(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 (rcs *KeeperRegistrySettings) Create22OnchainConfig(registrar string, registryOwnerAddress, chainModuleAddress common.Address, reorgProtectionEnabled bool) i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig { return i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig{ PaymentPremiumPPB: rcs.PaymentPremiumPPB, @@ -318,2077 +236,33 @@ 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, linkTokenAddr string) ([]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 + WETHTokenAddr string } -// 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/go.mod b/integration-tests/go.mod index d1e06d7feb2..d758e43c064 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -8,6 +8,7 @@ replace github.com/smartcontractkit/chainlink/v2 => ../ require ( github.com/avast/retry-go/v4 v4.5.1 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df + github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 github.com/fxamacker/cbor/v2 v2.5.0 @@ -27,10 +28,11 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240612013352-4fe4a2e2ed0f + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240620164046-1c03d0a97b20 github.com/smartcontractkit/chainlink-testing-framework v1.30.5 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 + github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/smartcontractkit/seth v1.0.12-0.20240618124527-ca057b90a33b github.com/smartcontractkit/wasp v0.4.7 @@ -44,6 +46,7 @@ require ( golang.org/x/sync v0.6.0 golang.org/x/text v0.14.0 gopkg.in/guregu/null.v4 v4.0.0 + k8s.io/apimachinery v0.28.2 ) // avoids ambigious imports of indirect dependencies @@ -111,7 +114,6 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/chzyer/readline v1.5.1 // indirect @@ -381,7 +383,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 // indirect + github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect @@ -470,7 +472,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.28.2 // indirect k8s.io/apiextensions-apiserver v0.25.3 // indirect - k8s.io/apimachinery v0.28.2 // indirect k8s.io/cli-runtime v0.25.11 // indirect k8s.io/client-go v0.28.2 // indirect k8s.io/component-base v0.26.2 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 95a0536abf5..b5c6b7aba8d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1512,8 +1512,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240612013352-4fe4a2e2ed0f h1:MfEG+nDHibAFFF1iirnF849YJT8ne+adVEf8p2fVze8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240612013352-4fe4a2e2ed0f/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240620164046-1c03d0a97b20 h1:Ea3shtV50R1qMkLbDaOwio2C+Ia1dB7pJQzpm7vHzxM= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240620164046-1c03d0a97b20/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= @@ -1526,14 +1526,16 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.202405 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696/go.mod h1:OiWUTrrpSLLTMh7FINWjEh6mmDJCVPaC4yEsDCVaWdU= github.com/smartcontractkit/chainlink-testing-framework v1.30.5 h1:RBeQkaUH095L/hOH6JbfScAo4jkI0osBp8kgULnGwos= github.com/smartcontractkit/chainlink-testing-framework v1.30.5/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= +github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= +github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/seth v1.0.12-0.20240618124527-ca057b90a33b h1:9to6XdJN1bIVrjLmWm9nyVaaKcIPcJKO8eTJjPYO5vs=