From 9ca4f04f97af46d64e7f17b8afedfd0f009f0d63 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com> Date: Wed, 1 May 2024 15:51:18 -0700 Subject: [PATCH 01/35] Bump version and update CHANGELOG for core v2.12.0 (#13075) Signed-off-by: Sneha Agnihotri --- .changeset/beige-socks-cover.md | 5 - .changeset/brave-dots-breathe.md | 7 -- .changeset/brown-penguins-grin.md | 5 - .changeset/chilled-bikes-unite.md | 5 - .changeset/curvy-weeks-cover.md | 5 - .changeset/cyan-crabs-explode.md | 5 - .changeset/dull-dingos-remember.md | 5 - .changeset/early-paws-end.md | 5 - .changeset/empty-tomatoes-yawn.md | 5 - .changeset/fast-students-accept.md | 5 - .changeset/flat-guests-marry.md | 6 -- .changeset/forty-feet-train.md | 5 - .changeset/four-shoes-trade.md | 5 - .changeset/fresh-lizards-love.md | 5 - .changeset/fresh-moles-explode.md | 5 - .changeset/fresh-rice-learn.md | 5 - .changeset/fuzzy-pans-destroy.md | 5 - .changeset/gold-bottles-tell.md | 5 - .changeset/great-rockets-obey.md | 5 - .changeset/hot-dryers-flash.md | 5 - .changeset/hungry-ways-add.md | 6 -- .changeset/kind-deers-leave.md | 5 - .changeset/lovely-jeans-confess.md | 6 -- .changeset/lucky-ghosts-give.md | 5 - .changeset/lucky-windows-taste.md | 5 - .changeset/many-pillows-reflect.md | 5 - .changeset/new-forks-grab.md | 5 - .changeset/olive-knives-happen.md | 5 - .changeset/orange-squids-kick.md | 5 - .changeset/perfect-dancers-guess.md | 5 - .changeset/pink-schools-provide.md | 5 - .changeset/plenty-wombats-grab.md | 5 - .changeset/poor-masks-fold.md | 6 -- .changeset/poor-socks-travel.md | 5 - .changeset/pretty-flies-fold.md | 5 - .changeset/pretty-kangaroos-tell.md | 5 - .changeset/proud-toys-travel.md | 5 - .changeset/quick-fishes-heal.md | 5 - .changeset/real-numbers-taste.md | 5 - .changeset/rich-jars-flow.md | 5 - .changeset/silver-otters-play.md | 5 - .changeset/sixty-readers-mix.md | 5 - .changeset/smooth-comics-love.md | 5 - .changeset/soft-hotels-decide.md | 5 - .changeset/sour-jars-cross.md | 13 --- .changeset/spotty-cooks-think.md | 5 - .changeset/stale-terms-march.md | 7 -- .changeset/sweet-sloths-laugh.md | 5 - .changeset/swift-horses-unite.md | 5 - .changeset/tasty-lions-rhyme.md | 5 - .changeset/tender-crews-jam.md | 5 - .changeset/thirty-students-explain.md | 5 - .changeset/tidy-trees-tie.md | 5 - .changeset/tricky-bats-exist.md | 5 - .changeset/two-countries-lay.md | 5 - .changeset/warm-impalas-return.md | 5 - .changeset/weak-emus-reply.md | 5 - .changeset/witty-icons-rhyme.md | 5 - .changeset/witty-numbers-sleep.md | 5 - CHANGELOG.md | 142 ++++++++++++++++++++++++++ package.json | 2 +- 61 files changed, 143 insertions(+), 312 deletions(-) delete mode 100644 .changeset/beige-socks-cover.md delete mode 100644 .changeset/brave-dots-breathe.md delete mode 100644 .changeset/brown-penguins-grin.md delete mode 100644 .changeset/chilled-bikes-unite.md delete mode 100644 .changeset/curvy-weeks-cover.md delete mode 100644 .changeset/cyan-crabs-explode.md delete mode 100644 .changeset/dull-dingos-remember.md delete mode 100644 .changeset/early-paws-end.md delete mode 100644 .changeset/empty-tomatoes-yawn.md delete mode 100644 .changeset/fast-students-accept.md delete mode 100644 .changeset/flat-guests-marry.md delete mode 100644 .changeset/forty-feet-train.md delete mode 100644 .changeset/four-shoes-trade.md delete mode 100644 .changeset/fresh-lizards-love.md delete mode 100644 .changeset/fresh-moles-explode.md delete mode 100644 .changeset/fresh-rice-learn.md delete mode 100644 .changeset/fuzzy-pans-destroy.md delete mode 100644 .changeset/gold-bottles-tell.md delete mode 100644 .changeset/great-rockets-obey.md delete mode 100644 .changeset/hot-dryers-flash.md delete mode 100644 .changeset/hungry-ways-add.md delete mode 100644 .changeset/kind-deers-leave.md delete mode 100644 .changeset/lovely-jeans-confess.md delete mode 100644 .changeset/lucky-ghosts-give.md delete mode 100644 .changeset/lucky-windows-taste.md delete mode 100644 .changeset/many-pillows-reflect.md delete mode 100644 .changeset/new-forks-grab.md delete mode 100644 .changeset/olive-knives-happen.md delete mode 100644 .changeset/orange-squids-kick.md delete mode 100644 .changeset/perfect-dancers-guess.md delete mode 100644 .changeset/pink-schools-provide.md delete mode 100644 .changeset/plenty-wombats-grab.md delete mode 100644 .changeset/poor-masks-fold.md delete mode 100644 .changeset/poor-socks-travel.md delete mode 100644 .changeset/pretty-flies-fold.md delete mode 100644 .changeset/pretty-kangaroos-tell.md delete mode 100644 .changeset/proud-toys-travel.md delete mode 100644 .changeset/quick-fishes-heal.md delete mode 100644 .changeset/real-numbers-taste.md delete mode 100644 .changeset/rich-jars-flow.md delete mode 100644 .changeset/silver-otters-play.md delete mode 100644 .changeset/sixty-readers-mix.md delete mode 100644 .changeset/smooth-comics-love.md delete mode 100644 .changeset/soft-hotels-decide.md delete mode 100644 .changeset/sour-jars-cross.md delete mode 100644 .changeset/spotty-cooks-think.md delete mode 100644 .changeset/stale-terms-march.md delete mode 100644 .changeset/sweet-sloths-laugh.md delete mode 100644 .changeset/swift-horses-unite.md delete mode 100644 .changeset/tasty-lions-rhyme.md delete mode 100644 .changeset/tender-crews-jam.md delete mode 100644 .changeset/thirty-students-explain.md delete mode 100644 .changeset/tidy-trees-tie.md delete mode 100644 .changeset/tricky-bats-exist.md delete mode 100644 .changeset/two-countries-lay.md delete mode 100644 .changeset/warm-impalas-return.md delete mode 100644 .changeset/weak-emus-reply.md delete mode 100644 .changeset/witty-icons-rhyme.md delete mode 100644 .changeset/witty-numbers-sleep.md diff --git a/.changeset/beige-socks-cover.md b/.changeset/beige-socks-cover.md deleted file mode 100644 index 0b7c22d01e5..00000000000 --- a/.changeset/beige-socks-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal changes to core required by change BCF3168 in common to add relayer set diff --git a/.changeset/brave-dots-breathe.md b/.changeset/brave-dots-breathe.md deleted file mode 100644 index f1ae4f4d21e..00000000000 --- a/.changeset/brave-dots-breathe.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": minor ---- - -Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. -Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. -#nops #added diff --git a/.changeset/brown-penguins-grin.md b/.changeset/brown-penguins-grin.md deleted file mode 100644 index 24a06a030fc..00000000000 --- a/.changeset/brown-penguins-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix in memory data source cache changes/bug that only allowed pipeline results where none of the data sources failed. #bugfix diff --git a/.changeset/chilled-bikes-unite.md b/.changeset/chilled-bikes-unite.md deleted file mode 100644 index e3e54852002..00000000000 --- a/.changeset/chilled-bikes-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add script to create test database user and update docs diff --git a/.changeset/curvy-weeks-cover.md b/.changeset/curvy-weeks-cover.md deleted file mode 100644 index 0b19df8ad16..00000000000 --- a/.changeset/curvy-weeks-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Keystone contract wrappers updated diff --git a/.changeset/cyan-crabs-explode.md b/.changeset/cyan-crabs-explode.md deleted file mode 100644 index 5018e2d555c..00000000000 --- a/.changeset/cyan-crabs-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add support for workflow jobs to Operator UI #wip #added diff --git a/.changeset/dull-dingos-remember.md b/.changeset/dull-dingos-remember.md deleted file mode 100644 index 7c1b748cff7..00000000000 --- a/.changeset/dull-dingos-remember.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -use safe lib for approve #bugfix diff --git a/.changeset/early-paws-end.md b/.changeset/early-paws-end.md deleted file mode 100644 index 1a3edb5083f..00000000000 --- a/.changeset/early-paws-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -generate gethwrappers for updating node operators in capability registry #internal diff --git a/.changeset/empty-tomatoes-yawn.md b/.changeset/empty-tomatoes-yawn.md deleted file mode 100644 index 3f6e94b79a9..00000000000 --- a/.changeset/empty-tomatoes-yawn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add a comment to Chain Reader Service constructor that specifies that anonymous events are not supported. diff --git a/.changeset/fast-students-accept.md b/.changeset/fast-students-accept.md deleted file mode 100644 index 8813f3a7812..00000000000 --- a/.changeset/fast-students-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Optimize workflow engine tests diff --git a/.changeset/flat-guests-marry.md b/.changeset/flat-guests-marry.md deleted file mode 100644 index c1eb6549a96..00000000000 --- a/.changeset/flat-guests-marry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Gas Estimator L1Oracles to be chain specific -#removed cmd/arbgas diff --git a/.changeset/forty-feet-train.md b/.changeset/forty-feet-train.md deleted file mode 100644 index f5ea60fd061..00000000000 --- a/.changeset/forty-feet-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Bumping chainlink-automation version to v1.0.3 diff --git a/.changeset/four-shoes-trade.md b/.changeset/four-shoes-trade.md deleted file mode 100644 index cb5c9f4be6b..00000000000 --- a/.changeset/four-shoes-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Removed AppConfig from Evm config #internal diff --git a/.changeset/fresh-lizards-love.md b/.changeset/fresh-lizards-love.md deleted file mode 100644 index 8e6e5d5cfef..00000000000 --- a/.changeset/fresh-lizards-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updates required to work with chainlink-common changes to support grpc streams for capabilities diff --git a/.changeset/fresh-moles-explode.md b/.changeset/fresh-moles-explode.md deleted file mode 100644 index 205002b40a0..00000000000 --- a/.changeset/fresh-moles-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated diff --git a/.changeset/fresh-rice-learn.md b/.changeset/fresh-rice-learn.md deleted file mode 100644 index 6425cdd4581..00000000000 --- a/.changeset/fresh-rice-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Moved test functions under evm package to support evm extraction #internal diff --git a/.changeset/fuzzy-pans-destroy.md b/.changeset/fuzzy-pans-destroy.md deleted file mode 100644 index 3cff19f8d8a..00000000000 --- a/.changeset/fuzzy-pans-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Use sqlutil instead of pg.Opts/Q/Queryer #internal diff --git a/.changeset/gold-bottles-tell.md b/.changeset/gold-bottles-tell.md deleted file mode 100644 index 5289f368a55..00000000000 --- a/.changeset/gold-bottles-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added : Re-enable abandoned transaction tracker diff --git a/.changeset/great-rockets-obey.md b/.changeset/great-rockets-obey.md deleted file mode 100644 index b90bc810a01..00000000000 --- a/.changeset/great-rockets-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Keystone wrapper regenerate diff --git a/.changeset/hot-dryers-flash.md b/.changeset/hot-dryers-flash.md deleted file mode 100644 index 8423420589d..00000000000 --- a/.changeset/hot-dryers-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services: update llo & versioning to use sqlutil #internal diff --git a/.changeset/hungry-ways-add.md b/.changeset/hungry-ways-add.md deleted file mode 100644 index 657494de605..00000000000 --- a/.changeset/hungry-ways-add.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix -vrf fix replay number of blocks logic and add logging for job specs diff --git a/.changeset/kind-deers-leave.md b/.changeset/kind-deers-leave.md deleted file mode 100644 index ef88e78241c..00000000000 --- a/.changeset/kind-deers-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -bump mockery in makefile #updated diff --git a/.changeset/lovely-jeans-confess.md b/.changeset/lovely-jeans-confess.md deleted file mode 100644 index 50fc70c2c14..00000000000 --- a/.changeset/lovely-jeans-confess.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -#nops : Enable configurable client error regexes for error classification -#added : New toml configuration options for [EVM.NodePool.Errors] to pass regexes on NonceTooLow, NonceTooHigh, ReplacementTransactionUnderpriced, LimitReached, TransactionAlreadyInMempool, TerminallyUnderpriced, InsufficientEth, TxFeeExceedsCap, L2FeeTooLow, L2FeeTooHigh, L2Full, TransactionAlreadyMined, Fatal, and ServiceUnavailable. diff --git a/.changeset/lucky-ghosts-give.md b/.changeset/lucky-ghosts-give.md deleted file mode 100644 index 2ce47a6978b..00000000000 --- a/.changeset/lucky-ghosts-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/keystore: switch to sqlutil.DataStore #internal diff --git a/.changeset/lucky-windows-taste.md b/.changeset/lucky-windows-taste.md deleted file mode 100644 index bfcf559adb5..00000000000 --- a/.changeset/lucky-windows-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Validate support for postgresql-client 16, and update docker image's bundled postgresql-client from 15 to 16. #nops #updated diff --git a/.changeset/many-pillows-reflect.md b/.changeset/many-pillows-reflect.md deleted file mode 100644 index 6de57ecc2a4..00000000000 --- a/.changeset/many-pillows-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/keeper: switch to sqlutil.DataSource #internal diff --git a/.changeset/new-forks-grab.md b/.changeset/new-forks-grab.md deleted file mode 100644 index 350b5baafb0..00000000000 --- a/.changeset/new-forks-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Drop unused queryTimeout config from TXM strategy #internal diff --git a/.changeset/olive-knives-happen.md b/.changeset/olive-knives-happen.md deleted file mode 100644 index 7f522c96ff1..00000000000 --- a/.changeset/olive-knives-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Generic Plugin `onchainSigningStrategy` support diff --git a/.changeset/orange-squids-kick.md b/.changeset/orange-squids-kick.md deleted file mode 100644 index a934e70063d..00000000000 --- a/.changeset/orange-squids-kick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Remote Trigger setup diff --git a/.changeset/perfect-dancers-guess.md b/.changeset/perfect-dancers-guess.md deleted file mode 100644 index 6ee4099c45a..00000000000 --- a/.changeset/perfect-dancers-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Rename workflow tags to labels diff --git a/.changeset/pink-schools-provide.md b/.changeset/pink-schools-provide.md deleted file mode 100644 index 6b2aa5ea0c4..00000000000 --- a/.changeset/pink-schools-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. diff --git a/.changeset/plenty-wombats-grab.md b/.changeset/plenty-wombats-grab.md deleted file mode 100644 index 84fb96f8b80..00000000000 --- a/.changeset/plenty-wombats-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Regenerate Keystone wrappers diff --git a/.changeset/poor-masks-fold.md b/.changeset/poor-masks-fold.md deleted file mode 100644 index 1564aa0791f..00000000000 --- a/.changeset/poor-masks-fold.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -Move JuelsPerFeeCoinCacheDuration under JuelsPerFeeCoinCache struct in config. Rename JuelsPerFeeCoinCacheDuration to updateInterval. Add stalenessAlertThreshold to JuelsPerFeeCoinCache config. -StalenessAlertThreshold cfg option has a default of 24 hours which means that it doesn't have to be set unless we want to override the duration after which a stale cache should start throwing errors. diff --git a/.changeset/poor-socks-travel.md b/.changeset/poor-socks-travel.md deleted file mode 100644 index 88986845095..00000000000 --- a/.changeset/poor-socks-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/ocr2/plugins/ocr2keeper/evmregister/v21/upkeepstate: use sqlutil instead of pg.QOpts #internal diff --git a/.changeset/pretty-flies-fold.md b/.changeset/pretty-flies-fold.md deleted file mode 100644 index d67a3117e14..00000000000 --- a/.changeset/pretty-flies-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -cor/services/relay/evm/mercury: switch to sqlutil.DataStore #internal diff --git a/.changeset/pretty-kangaroos-tell.md b/.changeset/pretty-kangaroos-tell.md deleted file mode 100644 index 946869b1ca0..00000000000 --- a/.changeset/pretty-kangaroos-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add check for valid semvar value for changeset file #internal diff --git a/.changeset/proud-toys-travel.md b/.changeset/proud-toys-travel.md deleted file mode 100644 index e2b1f0c7269..00000000000 --- a/.changeset/proud-toys-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Improving LogPoller read queries by properly sorting by multiple columns #updated diff --git a/.changeset/quick-fishes-heal.md b/.changeset/quick-fishes-heal.md deleted file mode 100644 index 966e74c843a..00000000000 --- a/.changeset/quick-fishes-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- -#changed -Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. diff --git a/.changeset/real-numbers-taste.md b/.changeset/real-numbers-taste.md deleted file mode 100644 index d9f545444c2..00000000000 --- a/.changeset/real-numbers-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/functions: switch to sqlutil.DataStore #internal diff --git a/.changeset/rich-jars-flow.md b/.changeset/rich-jars-flow.md deleted file mode 100644 index cb72503fe0d..00000000000 --- a/.changeset/rich-jars-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Narrowing topic, data_word indexes by adding (evm_chain_id, address, event_sig) to the index definition #db_update diff --git a/.changeset/silver-otters-play.md b/.changeset/silver-otters-play.md deleted file mode 100644 index 433011b5c76..00000000000 --- a/.changeset/silver-otters-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Validate user email before asking for a password in the chainlink CLI. diff --git a/.changeset/sixty-readers-mix.md b/.changeset/sixty-readers-mix.md deleted file mode 100644 index a6782a5b276..00000000000 --- a/.changeset/sixty-readers-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add support for X Layer (X1) #added diff --git a/.changeset/smooth-comics-love.md b/.changeset/smooth-comics-love.md deleted file mode 100644 index 6d41284978d..00000000000 --- a/.changeset/smooth-comics-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -update keystone gethwrapper with remove operator function #internal diff --git a/.changeset/soft-hotels-decide.md b/.changeset/soft-hotels-decide.md deleted file mode 100644 index 75b4cadd4e5..00000000000 --- a/.changeset/soft-hotels-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -switch more EVM components to use sqlutil.DataStore #internal diff --git a/.changeset/sour-jars-cross.md b/.changeset/sour-jars-cross.md deleted file mode 100644 index b904e8e3dd0..00000000000 --- a/.changeset/sour-jars-cross.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"chainlink": patch ---- - -#added - -Add configurability to mercury transmitter - -```toml -[Mercury.Transmitter] -TransmitQueueMaxSize = 10_000 # Default -TransmitTimeout = "5s" # Default -``` diff --git a/.changeset/spotty-cooks-think.md b/.changeset/spotty-cooks-think.md deleted file mode 100644 index e645de27beb..00000000000 --- a/.changeset/spotty-cooks-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fix txdb documentation typos diff --git a/.changeset/stale-terms-march.md b/.changeset/stale-terms-march.md deleted file mode 100644 index 72ba417eac3..00000000000 --- a/.changeset/stale-terms-march.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": patch ---- - -Bump libocr => fd3cab206b2ca3b7ff207996b95673b2d6303ec4 - -#internal diff --git a/.changeset/sweet-sloths-laugh.md b/.changeset/sweet-sloths-laugh.md deleted file mode 100644 index cbc72913ec9..00000000000 --- a/.changeset/sweet-sloths-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/sessions: switch to sqlutil.DataSource #internal diff --git a/.changeset/swift-horses-unite.md b/.changeset/swift-horses-unite.md deleted file mode 100644 index d9d426efe6d..00000000000 --- a/.changeset/swift-horses-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/bridges: use sqlutil.DataSource #internal diff --git a/.changeset/tasty-lions-rhyme.md b/.changeset/tasty-lions-rhyme.md deleted file mode 100644 index b80f1337bce..00000000000 --- a/.changeset/tasty-lions-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add getters #internal diff --git a/.changeset/tender-crews-jam.md b/.changeset/tender-crews-jam.md deleted file mode 100644 index 41b4f0a7633..00000000000 --- a/.changeset/tender-crews-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -vrfv2plus - account for num words in coordinator gas overhead in v2plus wrapper diff --git a/.changeset/thirty-students-explain.md b/.changeset/thirty-students-explain.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/thirty-students-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/tidy-trees-tie.md b/.changeset/tidy-trees-tie.md deleted file mode 100644 index 7ff415e9de4..00000000000 --- a/.changeset/tidy-trees-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#changed Updating the log trigger log provider's readMaxBatchSize to 56 diff --git a/.changeset/tricky-bats-exist.md b/.changeset/tricky-bats-exist.md deleted file mode 100644 index 3c748353859..00000000000 --- a/.changeset/tricky-bats-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -minor fixes #bugfix diff --git a/.changeset/two-countries-lay.md b/.changeset/two-countries-lay.md deleted file mode 100644 index f3d78e6a2e6..00000000000 --- a/.changeset/two-countries-lay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -update keystone gethwrapper #internal diff --git a/.changeset/warm-impalas-return.md b/.changeset/warm-impalas-return.md deleted file mode 100644 index 167d831692c..00000000000 --- a/.changeset/warm-impalas-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) diff --git a/.changeset/weak-emus-reply.md b/.changeset/weak-emus-reply.md deleted file mode 100644 index ef0c1fe4dae..00000000000 --- a/.changeset/weak-emus-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updated FindTxesWithAttemptsAndReceiptsByIdsAndState method signature to accept int64 for tx ID instead of big.Int diff --git a/.changeset/witty-icons-rhyme.md b/.changeset/witty-icons-rhyme.md deleted file mode 100644 index 25d9cf3b1d3..00000000000 --- a/.changeset/witty-icons-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -offchain settlement fix #bugfix diff --git a/.changeset/witty-numbers-sleep.md b/.changeset/witty-numbers-sleep.md deleted file mode 100644 index d42664d9f76..00000000000 --- a/.changeset/witty-numbers-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Support for retention in LogPoller's filters registered by ContractTransmitter #changed diff --git a/CHANGELOG.md b/CHANGELOG.md index 336b896ce78..314626a0bd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,145 @@ # Changelog Chainlink Core +## 2.12.0 - UNRELEASED + +### Minor Changes + +- [#13000](https://github.com/smartcontractkit/chainlink/pull/13000) [`1b994043b0`](https://github.com/smartcontractkit/chainlink/commit/1b994043b00cad9e0c900b6d12173dd1008480a5) Thanks [@ettec](https://github.com/ettec)! - #internal changes to core required by change BCF3168 in common to add relayer set + +- [#12867](https://github.com/smartcontractkit/chainlink/pull/12867) [`27d9413286`](https://github.com/smartcontractkit/chainlink/commit/27d941328655e0cde608c1eff47de736c11e2e58) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. + Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. + #nops #added + +- [#12914](https://github.com/smartcontractkit/chainlink/pull/12914) [`28df745115`](https://github.com/smartcontractkit/chainlink/commit/28df74511568df989944ee92cfd625a5d22a2840) Thanks [@krehermann](https://github.com/krehermann)! - #internal Add script to create test database user and update docs + +- [#12837](https://github.com/smartcontractkit/chainlink/pull/12837) [`f7982fa718`](https://github.com/smartcontractkit/chainlink/commit/f7982fa718cd9dc6563019acd8dfc5a40475df9e) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - Add support for workflow jobs to Operator UI #wip #added + +- [#12686](https://github.com/smartcontractkit/chainlink/pull/12686) [`2e768c150b`](https://github.com/smartcontractkit/chainlink/commit/2e768c150b44eb3ac8e41e7bafdd46911be57397) Thanks [@nolag](https://github.com/nolag)! - Add a comment to Chain Reader Service constructor that specifies that anonymous events are not supported. + +- [#12650](https://github.com/smartcontractkit/chainlink/pull/12650) [`6991af26d9`](https://github.com/smartcontractkit/chainlink/commit/6991af26d9fa0e048b72a05f4f9c13f2306c0328) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Gas Estimator L1Oracles to be chain specific + #removed cmd/arbgas + +- [#12857](https://github.com/smartcontractkit/chainlink/pull/12857) [`d90229e7a7`](https://github.com/smartcontractkit/chainlink/commit/d90229e7a7011f8dc1c331dffb0ad1eeaddba46f) Thanks [@ettec](https://github.com/ettec)! - #internal Updates required to work with chainlink-common changes to support grpc streams for capabilities + +- [#12605](https://github.com/smartcontractkit/chainlink/pull/12605) [`1d9dd466e2`](https://github.com/smartcontractkit/chainlink/commit/1d9dd466e2933b7558949554b882f29f63d90b9f) Thanks [@reductionista](https://github.com/reductionista)! - core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated + +- [#12968](https://github.com/smartcontractkit/chainlink/pull/12968) [`c97781582b`](https://github.com/smartcontractkit/chainlink/commit/c97781582bbe0333332b985fb10a06edeaafa524) Thanks [@dimriou](https://github.com/dimriou)! - Moved test functions under evm package to support evm extraction #internal + +- [#12456](https://github.com/smartcontractkit/chainlink/pull/12456) [`78dd3e026a`](https://github.com/smartcontractkit/chainlink/commit/78dd3e026a81cb656b99ac62ce552369573ca736) Thanks [@jmank88](https://github.com/jmank88)! - Use sqlutil instead of pg.Opts/Q/Queryer #internal + +- [#12533](https://github.com/smartcontractkit/chainlink/pull/12533) [`ccb8cd85fe`](https://github.com/smartcontractkit/chainlink/commit/ccb8cd85fef8e3bbe3fb5580277a7bd7f477e6bb) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - #added : Re-enable abandoned transaction tracker + +- [#12760](https://github.com/smartcontractkit/chainlink/pull/12760) [`3f4573479c`](https://github.com/smartcontractkit/chainlink/commit/3f4573479c32dedf44f04261f9d5d4905f2542c7) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - #nops : Enable configurable client error regexes for error classification + #added : New toml configuration options for [EVM.NodePool.Errors] to pass regexes on NonceTooLow, NonceTooHigh, ReplacementTransactionUnderpriced, LimitReached, TransactionAlreadyInMempool, TerminallyUnderpriced, InsufficientEth, TxFeeExceedsCap, L2FeeTooLow, L2FeeTooHigh, L2Full, TransactionAlreadyMined, Fatal, and ServiceUnavailable. + +- [#12595](https://github.com/smartcontractkit/chainlink/pull/12595) [`e6d4814bda`](https://github.com/smartcontractkit/chainlink/commit/e6d4814bda908f1c0582b914d5aa803cecf333be) Thanks [@ilija42](https://github.com/ilija42)! - Move JuelsPerFeeCoinCacheDuration under JuelsPerFeeCoinCache struct in config. Rename JuelsPerFeeCoinCacheDuration to updateInterval. Add stalenessAlertThreshold to JuelsPerFeeCoinCache config. + StalenessAlertThreshold cfg option has a default of 24 hours which means that it doesn't have to be set unless we want to override the duration after which a stale cache should start throwing errors. + +- [#12767](https://github.com/smartcontractkit/chainlink/pull/12767) [`8db5ccfb39`](https://github.com/smartcontractkit/chainlink/commit/8db5ccfb39f86c9817fcad28292dbe6500821810) Thanks [@pavel-raykov](https://github.com/pavel-raykov)! - Validate user email before asking for a password in the chainlink CLI. + +- [#12851](https://github.com/smartcontractkit/chainlink/pull/12851) [`40064f0dfe`](https://github.com/smartcontractkit/chainlink/commit/40064f0dfecda6e404993dff056e7a666cca7d26) Thanks [@amit-momin](https://github.com/amit-momin)! - #internal Updated FindTxesWithAttemptsAndReceiptsByIdsAndState method signature to accept int64 for tx ID instead of big.Int + +### Patch Changes + +- [#12907](https://github.com/smartcontractkit/chainlink/pull/12907) [`f0439ec840`](https://github.com/smartcontractkit/chainlink/commit/f0439ec8408b39456a74c37df9a264782ed4725c) Thanks [@ilija42](https://github.com/ilija42)! - Fix in memory data source cache changes/bug that only allowed pipeline results where none of the data sources failed. #bugfix + +- [#12996](https://github.com/smartcontractkit/chainlink/pull/12996) [`0a37c0ed53`](https://github.com/smartcontractkit/chainlink/commit/0a37c0ed5346df509b545c88278c026cb2adf375) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Keystone contract wrappers updated + +- [#12923](https://github.com/smartcontractkit/chainlink/pull/12923) [`274a988985`](https://github.com/smartcontractkit/chainlink/commit/274a988985e0530676bdfedbdb35dec4cb9fe8b2) Thanks [@shileiwill](https://github.com/shileiwill)! - use safe lib for approve #bugfix + +- [#12991](https://github.com/smartcontractkit/chainlink/pull/12991) [`929312681f`](https://github.com/smartcontractkit/chainlink/commit/929312681fb27529915912e8bd6e4000559ea77f) Thanks [@cds95](https://github.com/cds95)! - generate gethwrappers for updating node operators in capability registry #internal + +- [#12959](https://github.com/smartcontractkit/chainlink/pull/12959) [`e482c79822`](https://github.com/smartcontractkit/chainlink/commit/e482c7982278e232acaaa4b3e9a79165faa35d1c) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Optimize workflow engine tests + +- [#12754](https://github.com/smartcontractkit/chainlink/pull/12754) [`4d9875ecba`](https://github.com/smartcontractkit/chainlink/commit/4d9875ecba9c7f672a9320d43cdb3d24a529f2ee) Thanks [@amirylm](https://github.com/amirylm)! - Bumping chainlink-automation version to v1.0.3 + +- [#12636](https://github.com/smartcontractkit/chainlink/pull/12636) [`bdc076c139`](https://github.com/smartcontractkit/chainlink/commit/bdc076c1395259298f520d741a3a1b397c3e0037) Thanks [@dimriou](https://github.com/dimriou)! - Removed AppConfig from Evm config #internal + +- [#12880](https://github.com/smartcontractkit/chainlink/pull/12880) [`8337fc821b`](https://github.com/smartcontractkit/chainlink/commit/8337fc821baf8011c6c73203482db85f5a44d7ae) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Keystone wrapper regenerate + +- [#12807](https://github.com/smartcontractkit/chainlink/pull/12807) [`dd41ee6c1f`](https://github.com/smartcontractkit/chainlink/commit/dd41ee6c1fb79333bfec4e8ef795a859e09e72c8) Thanks [@jmank88](https://github.com/jmank88)! - core/services: update llo & versioning to use sqlutil #internal + +- [#12887](https://github.com/smartcontractkit/chainlink/pull/12887) [`e87b83cd78`](https://github.com/smartcontractkit/chainlink/commit/e87b83cd78595c09061c199916c4bb9145e719b7) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - #bugfix + vrf fix replay number of blocks logic and add logging for job specs + +- [#12848](https://github.com/smartcontractkit/chainlink/pull/12848) [`91698020fb`](https://github.com/smartcontractkit/chainlink/commit/91698020fb695545eeb4befb2d73e36cc3ded0ab) Thanks [@poopoothegorilla](https://github.com/poopoothegorilla)! - bump mockery in makefile #updated + +- [#12810](https://github.com/smartcontractkit/chainlink/pull/12810) [`1fce16e735`](https://github.com/smartcontractkit/chainlink/commit/1fce16e735e417553c00680a3fcae2e081353095) Thanks [@jmank88](https://github.com/jmank88)! - core/services/keystore: switch to sqlutil.DataStore #internal + +- [#11936](https://github.com/smartcontractkit/chainlink/pull/11936) [`2b38bd8738`](https://github.com/smartcontractkit/chainlink/commit/2b38bd8738b4edf16e9913c90720820bc2b8dbd1) Thanks [@erikburt](https://github.com/erikburt)! - Validate support for postgresql-client 16, and update docker image's bundled postgresql-client from 15 to 16. #nops #updated + +- [#12820](https://github.com/smartcontractkit/chainlink/pull/12820) [`e523aa0bc7`](https://github.com/smartcontractkit/chainlink/commit/e523aa0bc7752fbf11dfbb842c8a411d345f30e7) Thanks [@jmank88](https://github.com/jmank88)! - core/services/keeper: switch to sqlutil.DataSource #internal + +- [#12859](https://github.com/smartcontractkit/chainlink/pull/12859) [`44c9b40e0a`](https://github.com/smartcontractkit/chainlink/commit/44c9b40e0a77be0609c33d06c3101d8a7163c3e7) Thanks [@dimriou](https://github.com/dimriou)! - Drop unused queryTimeout config from TXM strategy #internal + +- [#12909](https://github.com/smartcontractkit/chainlink/pull/12909) [`fa5b22773e`](https://github.com/smartcontractkit/chainlink/commit/fa5b22773e52744d3abab1a05cd12ecc2e103d88) Thanks [@vyzaldysanchez](https://github.com/vyzaldysanchez)! - #internal Generic Plugin `onchainSigningStrategy` support + +- [#12845](https://github.com/smartcontractkit/chainlink/pull/12845) [`63abd08cd5`](https://github.com/smartcontractkit/chainlink/commit/63abd08cd55b6dc31e74c6d3e50597eb8400eeb4) Thanks [@bolekk](https://github.com/bolekk)! - #internal Remote Trigger setup + +- [#12961](https://github.com/smartcontractkit/chainlink/pull/12961) [`e50d38b0bd`](https://github.com/smartcontractkit/chainlink/commit/e50d38b0bddc34aa0b97ae6bdf23c355b5619682) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Rename workflow tags to labels + +- [#12997](https://github.com/smartcontractkit/chainlink/pull/12997) [`8c8994e242`](https://github.com/smartcontractkit/chainlink/commit/8c8994e24284236645509b4c49152e6270ce0e35) Thanks [@george-dorin](https://github.com/george-dorin)! - #bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. + +- [#12888](https://github.com/smartcontractkit/chainlink/pull/12888) [`7c059b2c26`](https://github.com/smartcontractkit/chainlink/commit/7c059b2c26ed6d99a40403b4f690c0f3e08154b4) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Regenerate Keystone wrappers + +- [#12806](https://github.com/smartcontractkit/chainlink/pull/12806) [`9964dc82e5`](https://github.com/smartcontractkit/chainlink/commit/9964dc82e591f8653adb06f0b149a16e0b6cea40) Thanks [@jmank88](https://github.com/jmank88)! - core/services/ocr2/plugins/ocr2keeper/evmregister/v21/upkeepstate: use sqlutil instead of pg.QOpts #internal + +- [#12818](https://github.com/smartcontractkit/chainlink/pull/12818) [`6a0b4a9b09`](https://github.com/smartcontractkit/chainlink/commit/6a0b4a9b099663e3aed202f48f363afc4d111293) Thanks [@jmank88](https://github.com/jmank88)! - cor/services/relay/evm/mercury: switch to sqlutil.DataStore #internal + +- [#12947](https://github.com/smartcontractkit/chainlink/pull/12947) [`758ffd6da0`](https://github.com/smartcontractkit/chainlink/commit/758ffd6da097adac1f49ceded5e0998cdcb98a29) Thanks [@momentmaker](https://github.com/momentmaker)! - Add check for valid semvar value for changeset file #internal + +- [#13026](https://github.com/smartcontractkit/chainlink/pull/13026) [`e21be2a890`](https://github.com/smartcontractkit/chainlink/commit/e21be2a890a50bd3cbac60c450e3c2d68ddefbd3) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Improving LogPoller read queries by properly sorting by multiple columns #updated + +- [#12638](https://github.com/smartcontractkit/chainlink/pull/12638) [`bcf7653486`](https://github.com/smartcontractkit/chainlink/commit/bcf76534862b32503f4192e38b7e1cb4dd7e312d) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - #changed + Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. + +- [#12811](https://github.com/smartcontractkit/chainlink/pull/12811) [`6b0a7afe23`](https://github.com/smartcontractkit/chainlink/commit/6b0a7afe235399790c066dd725c437403a47a73e) Thanks [@jmank88](https://github.com/jmank88)! - core/services/functions: switch to sqlutil.DataStore #internal + +- [#12786](https://github.com/smartcontractkit/chainlink/pull/12786) [`fbb705c4f1`](https://github.com/smartcontractkit/chainlink/commit/fbb705c4f1338c6e0919d728adee827ec1e2007a) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Narrowing topic, data_word indexes by adding (evm_chain_id, address, event_sig) to the index definition #db_update + +- [#12747](https://github.com/smartcontractkit/chainlink/pull/12747) [`2729ef76f3`](https://github.com/smartcontractkit/chainlink/commit/2729ef76f34877a2e6e8644b2e67f3e5dfb0c2b6) Thanks [@friedemannf](https://github.com/friedemannf)! - Add support for X Layer (X1) #added + +- [#12979](https://github.com/smartcontractkit/chainlink/pull/12979) [`0c4c24ad8c`](https://github.com/smartcontractkit/chainlink/commit/0c4c24ad8c95e505cd2a29be711cc40e612658b0) Thanks [@cds95](https://github.com/cds95)! - update keystone gethwrapper with remove operator function #internal + +- [#12856](https://github.com/smartcontractkit/chainlink/pull/12856) [`0ec92765cc`](https://github.com/smartcontractkit/chainlink/commit/0ec92765ccd419973f4eab5b0cc38df212f4ad21) Thanks [@jmank88](https://github.com/jmank88)! - switch more EVM components to use sqlutil.DataStore #internal + +- [#12680](https://github.com/smartcontractkit/chainlink/pull/12680) [`f55d8be495`](https://github.com/smartcontractkit/chainlink/commit/f55d8be495a83c97ac5439672563400e12ec2ee7) Thanks [@samsondav](https://github.com/samsondav)! - #added + + Add configurability to mercury transmitter + + ```toml + [Mercury.Transmitter] + TransmitQueueMaxSize = 10_000 # Default + TransmitTimeout = "5s" # Default + ``` + +- [#13059](https://github.com/smartcontractkit/chainlink/pull/13059) [`ea08b5f08d`](https://github.com/smartcontractkit/chainlink/commit/ea08b5f08d84d2ff1ddfa2027660ff58a60219c3) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal fix txdb documentation typos + +- [#12902](https://github.com/smartcontractkit/chainlink/pull/12902) [`d1845e22d3`](https://github.com/smartcontractkit/chainlink/commit/d1845e22d3b057d9d736bc05c30f0db34c84a7e4) Thanks [@samsondav](https://github.com/samsondav)! - Bump libocr => fd3cab206b2ca3b7ff207996b95673b2d6303ec4 + + #internal + +- [#12809](https://github.com/smartcontractkit/chainlink/pull/12809) [`0af4acafbd`](https://github.com/smartcontractkit/chainlink/commit/0af4acafbdf243feea8507e421016933b0e538ca) Thanks [@jmank88](https://github.com/jmank88)! - core/sessions: switch to sqlutil.DataSource #internal + +- [#12808](https://github.com/smartcontractkit/chainlink/pull/12808) [`601c79f891`](https://github.com/smartcontractkit/chainlink/commit/601c79f89120dc0d98db63a528c79644ebb38132) Thanks [@jmank88](https://github.com/jmank88)! - core/bridges: use sqlutil.DataSource #internal + +- [#12903](https://github.com/smartcontractkit/chainlink/pull/12903) [`a293dfe797`](https://github.com/smartcontractkit/chainlink/commit/a293dfe7975b035a71eff7a6197e3ce5a25f1887) Thanks [@shileiwill](https://github.com/shileiwill)! - add getters #internal + +- [#12669](https://github.com/smartcontractkit/chainlink/pull/12669) [`3134ce8868`](https://github.com/smartcontractkit/chainlink/commit/3134ce8868ccc22bd4ae670c8b0bfda5fa78a332) Thanks [@leeyikjiun](https://github.com/leeyikjiun)! - vrfv2plus - account for num words in coordinator gas overhead in v2plus wrapper + +- [#13022](https://github.com/smartcontractkit/chainlink/pull/13022) [`2805fa6c9b`](https://github.com/smartcontractkit/chainlink/commit/2805fa6c9b469d535edcd3d66c08e1d22bbaa2d0) Thanks [@cds95](https://github.com/cds95)! - #internal + +- [#12951](https://github.com/smartcontractkit/chainlink/pull/12951) [`c98ea6413d`](https://github.com/smartcontractkit/chainlink/commit/c98ea6413dcdc02a7d0c82b9b36d3fce97dac94b) Thanks [@ogtownsend](https://github.com/ogtownsend)! - #changed Updating the log trigger log provider's readMaxBatchSize to 56 + +- [#12944](https://github.com/smartcontractkit/chainlink/pull/12944) [`167782c680`](https://github.com/smartcontractkit/chainlink/commit/167782c680b92b1e99ae3e9d1a8b87fd595dd644) Thanks [@shileiwill](https://github.com/shileiwill)! - minor fixes #bugfix + +- [#12906](https://github.com/smartcontractkit/chainlink/pull/12906) [`365c38be8b`](https://github.com/smartcontractkit/chainlink/commit/365c38be8b589d5ffa0b21755dcb40e2e4205652) Thanks [@cds95](https://github.com/cds95)! - update keystone gethwrapper #internal + +- [#12966](https://github.com/smartcontractkit/chainlink/pull/12966) [`ac7d3409ed`](https://github.com/smartcontractkit/chainlink/commit/ac7d3409ed9bc98af970ca75c3b92e41e4fb01cf) Thanks [@george-dorin](https://github.com/george-dorin)! - #added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) + +- [#12916](https://github.com/smartcontractkit/chainlink/pull/12916) [`7ec1d5b7ab`](https://github.com/smartcontractkit/chainlink/commit/7ec1d5b7abb51e100f7a6a48662e33703a589ecb) Thanks [@shileiwill](https://github.com/shileiwill)! - offchain settlement fix #bugfix + +- [#12998](https://github.com/smartcontractkit/chainlink/pull/12998) [`d50936ce38`](https://github.com/smartcontractkit/chainlink/commit/d50936ce3824d7ad6026f630172e9764a34cc08b) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Support for retention in LogPoller's filters registered by ContractTransmitter #changed ## 2.11.0 - 2024-04-30 @@ -215,6 +355,7 @@ `mercury_transmit_queue_push_error_count` Nops should consider alerting on these. - Mercury now implements a local cache for fetching prices for fees, which ought to reduce latency and load on the mercury server, as well as increasing performance. It is enabled by default and can be configured with the following new config variables: + ``` [Mercury] @@ -239,6 +380,7 @@ # mercury server before retrying. Setting this to zero will wait indefinitely. LatestReportDeadline = "5s" # Default ``` + - New prom metrics for the mercury cache: `mercury_cache_fetch_failure_count` `mercury_cache_hit_count` diff --git a/package.json b/package.json index 759f8aaea4d..c903ac23165 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.11.0", + "version": "2.12.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { From 9bd03c99930b504029bbb3eed4ecd1d00509cd49 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Wed, 1 May 2024 23:20:12 -0400 Subject: [PATCH 02/35] Run short tests once on CI (#13077) --- .github/workflows/ci-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index fbef1b8282c..1d7b58820b0 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -112,7 +112,7 @@ jobs: if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-go - name: Run short tests - if: ${{ needs.filter.outputs.changes == 'true' }} + if: ${{ needs.filter.outputs.changes == 'true' && matrix.type.cmd == 'go_core_tests' }} run: go test -short ./... - name: Setup Solana if: ${{ needs.filter.outputs.changes == 'true' }} From 841fe61daa90b980f1e1622d2f7bd8f850b55462 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 00:38:00 -0400 Subject: [PATCH 03/35] Rename type -> id (#13008) --- .changeset/bright-queens-joke.md | 5 + contracts/.changeset/old-seas-doubt.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 116 +++++++++------- .../src/v0.8/keystone/test/BaseTest.t.sol | 18 +-- ...CapabilityRegistry_AddCapabilityTest.t.sol | 17 ++- .../CapabilityRegistry_AddNodesTest.t.sol | 46 +++---- ...pabilityRegistry_DeprecateCapability.t.sol | 40 +++--- .../CapabilityRegistry_GetCapabilities.t.sol | 12 +- .../CapabilityRegistry_GetCapabilityIds.t.sol | 4 +- .../keystone_capability_registry.go | 126 +++++++++--------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/services/workflows/engine.go | 10 +- core/services/workflows/engine_test.go | 22 +-- core/services/workflows/models.go | 5 +- core/services/workflows/models_test.go | 58 ++++---- core/services/workflows/models_yaml.go | 72 +++++----- core/services/workflows/models_yaml_test.go | 2 +- .../workflows/marshalling/workflow_1.yaml | 6 +- .../workflows/marshalling/workflow_2.yaml | 6 +- .../marshalling/workflow_2_spec.json | 8 +- .../workflows/references/failing_1.yaml | 6 +- .../workflows/references/passing_1.yaml | 6 +- .../workflows/versioning/failing_1.yaml | 6 +- .../workflows/versioning/failing_2.yaml | 6 +- .../workflows/versioning/passing_1.yaml | 6 +- .../fixtures/workflows/workflow_schema.json | 16 +-- core/web/jobs_controller_test.go | 8 +- 27 files changed, 333 insertions(+), 301 deletions(-) create mode 100644 .changeset/bright-queens-joke.md create mode 100644 contracts/.changeset/old-seas-doubt.md diff --git a/.changeset/bright-queens-joke.md b/.changeset/bright-queens-joke.md new file mode 100644 index 00000000000..a9dc2c8eb6d --- /dev/null +++ b/.changeset/bright-queens-joke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Keystone - rename type -> id diff --git a/contracts/.changeset/old-seas-doubt.md b/contracts/.changeset/old-seas-doubt.md new file mode 100644 index 00000000000..d559b3f5641 --- /dev/null +++ b/contracts/.changeset/old-seas-doubt.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#internal Keystone - rename type to id diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index ed3a300ac40..9e0a67434fc 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -28,10 +28,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { bytes32 p2pId; /// @notice The signer address for application-layer message verification. address signer; - /// @notice The list of capability IDs this node supports. This list is + /// @notice The list of hashed capability IDs this node supports. This list is /// never empty and all capabilities are guaranteed to exist in the /// CapabilityRegistry. - bytes32[] supportedCapabilityIds; + bytes32[] supportedHashedCapabilityIds; } // CapabilityResponseType indicates whether remote response requires @@ -45,10 +45,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } struct Capability { - // Capability type, e.g. "data-streams-reports" + // The `labelledName` is a partially qualified ID for the capability. + // + // Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} + // Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` portion of the ID. + // + // Ex. id = "data-streams-reports:chain:ethereum@1.0.0" + // labelledName = "data-streams-reports:chain:ethereum" + // // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ - // Not "type" because that's a reserved keyword in Solidity. - bytes32 capabilityType; + bytes32 labelledName; // Semver, e.g., "1.2.3" // bytes32(string); must be valid Semver + max 32 characters. bytes32 version; @@ -92,8 +98,8 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice This error is thrown when trying to add a node without /// capabilities or with capabilities that do not exist. - /// @param capabilityIds The IDs of the capabilities that are being added. - error InvalidNodeCapabilities(bytes32[] capabilityIds); + /// @param hashedCapabilityIds The IDs of the capabilities that are being added. + error InvalidNodeCapabilities(bytes32[] hashedCapabilityIds); /// @notice This event is emitted when a new node is added /// @param p2pId The P2P ID of the node @@ -104,15 +110,15 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// exists. error CapabilityAlreadyExists(); - /// @notice This error is thrown when a capability with the provided ID is + /// @notice This error is thrown when a capability with the provided hashed ID is /// not found. - /// @param capabilityId The ID used for the lookup. - error CapabilityDoesNotExist(bytes32 capabilityId); + /// @param hashedCapabilityId The hashed ID used for the lookup. + error CapabilityDoesNotExist(bytes32 hashedCapabilityId); /// @notice This error is thrown when trying to deprecate a capability that /// is already deprecated. - /// @param capabilityId The ID of the capability that is already deprecated. - error CapabilityAlreadyDeprecated(bytes32 capabilityId); + /// @param hashedCapabilityId The hashed ID of the capability that is already deprecated. + error CapabilityAlreadyDeprecated(bytes32 hashedCapabilityId); /// @notice This error is thrown when trying to add a capability with a /// configuration contract that does not implement the required interface. @@ -138,16 +144,22 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { event NodeOperatorUpdated(uint256 nodeOperatorId, address indexed admin, string name); /// @notice This event is emitted when a new capability is added - /// @param capabilityId The ID of the newly added capability - event CapabilityAdded(bytes32 indexed capabilityId); + /// @param hashedCapabilityId The hashed ID of the newly added capability + event CapabilityAdded(bytes32 indexed hashedCapabilityId); /// @notice This event is emitted when a capability is deprecated - /// @param capabilityId The ID of the deprecated capability - event CapabilityDeprecated(bytes32 indexed capabilityId); + /// @param hashedCapabilityId The hashed ID of the deprecated capability + event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); mapping(bytes32 => Capability) private s_capabilities; - EnumerableSet.Bytes32Set private s_capabilityIds; - EnumerableSet.Bytes32Set private s_deprecatedCapabilityIds; + /// @notice Set of hashed capability IDs. + /// A hashed ID is created by the function `getHashedCapabilityId`. + EnumerableSet.Bytes32Set private s_hashedCapabilityIds; + /// @notice Set of deprecated hashed capability IDs, + /// A hashed ID is created by the function `getHashedCapabilityId`. + /// + /// Deprecated capabilities are skipped by the `getCapabilities` function. + EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds; /// @notice Mapping of node operators mapping(uint256 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators; @@ -227,14 +239,15 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; if (msg.sender != nodeOperator.admin) revert AccessForbidden(); - bool nodeExists = s_nodes[node.p2pId].supportedCapabilityIds.length > 0; + bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; if (nodeExists || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); - if (node.supportedCapabilityIds.length == 0) revert InvalidNodeCapabilities(node.supportedCapabilityIds); + if (node.supportedHashedCapabilityIds.length == 0) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); - for (uint256 j; j < node.supportedCapabilityIds.length; ++j) { - if (!s_capabilityIds.contains(node.supportedCapabilityIds[j])) - revert InvalidNodeCapabilities(node.supportedCapabilityIds); + for (uint256 j; j < node.supportedHashedCapabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(node.supportedHashedCapabilityIds[j])) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); } s_nodes[node.p2pId] = node; @@ -250,9 +263,8 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } function addCapability(Capability calldata capability) external onlyOwner { - bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); - - if (s_capabilityIds.contains(capabilityId)) revert CapabilityAlreadyExists(); + bytes32 hashedId = getHashedCapabilityId(capability.labelledName, capability.version); + if (s_hashedCapabilityIds.contains(hashedId)) revert CapabilityAlreadyExists(); if (capability.configurationContract != address(0)) { if ( @@ -263,24 +275,26 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); } - s_capabilityIds.add(capabilityId); - s_capabilities[capabilityId] = capability; + s_hashedCapabilityIds.add(hashedId); + s_capabilities[hashedId] = capability; - emit CapabilityAdded(capabilityId); + emit CapabilityAdded(hashedId); } /// @notice Deprecates a capability by adding it to the deprecated list - /// @param capabilityId The ID of the capability to deprecate - function deprecateCapability(bytes32 capabilityId) external onlyOwner { - if (!s_capabilityIds.contains(capabilityId)) revert CapabilityDoesNotExist(capabilityId); - if (s_deprecatedCapabilityIds.contains(capabilityId)) revert CapabilityAlreadyDeprecated(capabilityId); - - s_deprecatedCapabilityIds.add(capabilityId); - emit CapabilityDeprecated(capabilityId); + /// @param hashedCapabilityId The ID of the capability to deprecate + function deprecateCapability(bytes32 hashedCapabilityId) external onlyOwner { + if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId); + if (s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) + revert CapabilityAlreadyDeprecated(hashedCapabilityId); + + s_deprecatedHashedCapabilityIds.add(hashedCapabilityId); + emit CapabilityDeprecated(hashedCapabilityId); } - function getCapability(bytes32 capabilityID) public view returns (Capability memory) { - return s_capabilities[capabilityID]; + /// @notice This function returns a Capability by its hashed ID. Use `getHashedCapabilityId` to get the hashed ID. + function getCapability(bytes32 hashedId) public view returns (Capability memory) { + return s_capabilities[hashedId]; } /// @notice Returns all capabilities. This operation will copy capabilities @@ -288,21 +302,23 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// used by view accessors that are queried without any gas fees. /// @return Capability[] An array of capabilities function getCapabilities() external view returns (Capability[] memory) { - bytes32[] memory capabilityIds = s_capabilityIds.values(); + bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); // Solidity does not support dynamic arrays in memory, so we create a // fixed-size array and copy the capabilities into it. - Capability[] memory capabilities = new Capability[](capabilityIds.length - s_deprecatedCapabilityIds.length()); + Capability[] memory capabilities = new Capability[]( + hashedCapabilityIds.length - s_deprecatedHashedCapabilityIds.length() + ); // We need to keep track of the new index because we are skipping // deprecated capabilities. uint256 newIndex; - for (uint256 i; i < capabilityIds.length; ++i) { - bytes32 capabilityId = capabilityIds[i]; + for (uint256 i; i < hashedCapabilityIds.length; ++i) { + bytes32 hashedCapabilityId = hashedCapabilityIds[i]; - if (!s_deprecatedCapabilityIds.contains(capabilityId)) { - capabilities[newIndex] = getCapability(capabilityId); + if (!s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) { + capabilities[newIndex] = getCapability(hashedCapabilityId); newIndex++; } } @@ -310,16 +326,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { return capabilities; } - /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access + /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access /// @return bytes32 A unique identifier for the capability - function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { - return keccak256(abi.encodePacked(capabilityType, version)); + function getHashedCapabilityId(bytes32 labelledName, bytes32 version) public pure returns (bytes32) { + return keccak256(abi.encodePacked(labelledName, version)); } /// @notice Returns whether a capability is deprecated - /// @param capabilityId The ID of the capability to check + /// @param hashedCapabilityId The hashed ID of the capability to check /// @return bool True if the capability is deprecated, false otherwise - function isCapabilityDeprecated(bytes32 capabilityId) external view returns (bool) { - return s_deprecatedCapabilityIds.contains(capabilityId); + function isCapabilityDeprecated(bytes32 hashedCapabilityId) external view returns (bool) { + return s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId); } } diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 95c8d1e5d3d..b4d12f7ba73 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -11,9 +11,9 @@ contract BaseTest is Test, Constants { CapabilityConfigurationContract internal s_capabilityConfigurationContract; CapabilityRegistry.Capability internal s_basicCapability; CapabilityRegistry.Capability internal s_capabilityWithConfigurationContract; - bytes32 internal s_basicCapabilityId; + bytes32 internal s_basicHashedCapabilityId; bytes32 internal s_capabilityWithConfigurationContractId; - bytes32 internal s_nonExistentCapabilityId; + bytes32 internal s_nonExistentHashedCapabilityId; function setUp() public virtual { vm.startPrank(ADMIN); @@ -21,27 +21,27 @@ contract BaseTest is Test, Constants { s_capabilityConfigurationContract = new CapabilityConfigurationContract(); s_basicCapability = CapabilityRegistry.Capability({ - capabilityType: "data-streams-reports", + labelledName: "data-streams-reports", version: "1.0.0", responseType: CapabilityRegistry.CapabilityResponseType.REPORT, configurationContract: address(0) }); s_capabilityWithConfigurationContract = CapabilityRegistry.Capability({ - capabilityType: "read-ethereum-mainnet-gas-price", + labelledName: "read-ethereum-mainnet-gas-price", version: "1.0.2", responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, configurationContract: address(s_capabilityConfigurationContract) }); - s_basicCapabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + s_basicHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityWithConfigurationContractId = s_capabilityRegistry.getCapabilityID( - s_capabilityWithConfigurationContract.capabilityType, + s_capabilityWithConfigurationContractId = s_capabilityRegistry.getHashedCapabilityId( + s_capabilityWithConfigurationContract.labelledName, s_capabilityWithConfigurationContract.version ); - s_nonExistentCapabilityId = s_capabilityRegistry.getCapabilityID("non-existent-capability", "1.0.0"); + s_nonExistentHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol index cf1bc6c8d73..dbcc0ae1712 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -47,10 +47,13 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_AddCapability_NoConfigurationContract() public { s_capabilityRegistry.addCapability(s_basicCapability); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32("data-streams-reports"), + bytes32("1.0.0") + ); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); - assertEq(storedCapability.capabilityType, s_basicCapability.capabilityType); + assertEq(storedCapability.labelledName, s_basicCapability.labelledName); assertEq(storedCapability.version, s_basicCapability.version); assertEq(uint256(storedCapability.responseType), uint256(s_basicCapability.responseType)); assertEq(storedCapability.configurationContract, s_basicCapability.configurationContract); @@ -59,13 +62,13 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_AddCapability_WithConfiguration() public { s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - bytes32(s_capabilityWithConfigurationContract.capabilityType), + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32(s_capabilityWithConfigurationContract.labelledName), bytes32(s_capabilityWithConfigurationContract.version) ); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); - assertEq(storedCapability.capabilityType, s_capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.labelledName, s_capabilityWithConfigurationContract.labelledName); assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); assertEq(uint256(storedCapability.responseType), uint256(s_capabilityWithConfigurationContract.responseType)); assertEq(storedCapability.configurationContract, s_capabilityWithConfigurationContract.configurationContract); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol index fe85c144eea..e179cc5cea6 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -22,14 +22,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(STRANGER); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); @@ -40,14 +40,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); s_capabilityRegistry.addNodes(nodes); @@ -59,14 +59,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); @@ -77,15 +77,15 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](0); + bytes32[] memory hashedCapabilityIds = new bytes32[](0); nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_capabilityRegistry.addNodes(nodes); } @@ -93,17 +93,17 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_nonExistentCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_capabilityRegistry.addNodes(nodes); } @@ -111,15 +111,15 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectEmit(address(s_capabilityRegistry)); @@ -129,8 +129,8 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); - assertEq(node.supportedCapabilityIds.length, 2); - assertEq(node.supportedCapabilityIds[0], s_basicCapabilityId); - assertEq(node.supportedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(node.supportedHashedCapabilityIds.length, 2); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol index 2e64ab7411f..b2f67339767 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol @@ -6,7 +6,7 @@ import {BaseTest} from "./BaseTest.t.sol"; import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract CapabilityRegistry_AddCapabilityTest is BaseTest { - event CapabilityDeprecated(bytes32 indexed capabilityId); + event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); function setUp() public override { BaseTest.setUp(); @@ -17,53 +17,55 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } function test_RevertWhen_CapabilityDoesNotExist() public { vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentCapabilityId) + abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) ); - s_capabilityRegistry.deprecateCapability(s_nonExistentCapabilityId); + s_capabilityRegistry.deprecateCapability(s_nonExistentHashedCapabilityId); } function test_RevertWhen_CapabilityAlreadyDeprecated() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyDeprecated.selector, capabilityId)); - s_capabilityRegistry.deprecateCapability(capabilityId); + vm.expectRevert( + abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyDeprecated.selector, hashedCapabilityId) + ); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } function test_DeprecatesCapability() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); - assertEq(s_capabilityRegistry.isCapabilityDeprecated(capabilityId), true); + assertEq(s_capabilityRegistry.isCapabilityDeprecated(hashedCapabilityId), true); } function test_EmitsEvent() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); vm.expectEmit(address(s_capabilityRegistry)); - emit CapabilityDeprecated(capabilityId); - s_capabilityRegistry.deprecateCapability(capabilityId); + emit CapabilityDeprecated(hashedCapabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol index b14397ba4ef..010fb619ba8 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol @@ -17,12 +17,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { assertEq(capabilities.length, 2); - assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].labelledName, "data-streams-reports"); assertEq(capabilities[0].version, "1.0.0"); assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); assertEq(capabilities[0].configurationContract, address(0)); - assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[1].version, "1.0.2"); assertEq( uint256(capabilities[1].responseType), @@ -32,16 +32,16 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { } function test_ExcludesDeprecatedCapabilities() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); assertEq(capabilities.length, 1); - assertEq(capabilities[0].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[0].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[0].version, "1.0.2"); assertEq( uint256(capabilities[0].responseType), diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol index de7810b4c15..b3dc333f5c3 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol @@ -13,12 +13,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { assertEq(capabilities.length, 2); - assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].labelledName, "data-streams-reports"); assertEq(capabilities[0].version, "1.0.0"); assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); assertEq(capabilities[0].configurationContract, address(0)); - assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[1].version, "1.0.2"); assertEq( uint256(capabilities[1].responseType), diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index b54a101d44e..8ea5e29d99c 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -31,17 +31,17 @@ var ( ) type CapabilityRegistryCapability struct { - CapabilityType [32]byte + LabelledName [32]byte Version [32]byte ResponseType uint8 ConfigurationContract common.Address } type CapabilityRegistryNode struct { - NodeOperatorId *big.Int - P2pId [32]byte - Signer common.Address - SupportedCapabilityIds [][32]byte + NodeOperatorId *big.Int + P2pId [32]byte + Signer common.Address + SupportedHashedCapabilityIds [][32]byte } type CapabilityRegistryNodeOperator struct { @@ -50,8 +50,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"capabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf634314610194578063229111f5146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf63431461019457806336b402fb146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -212,9 +212,9 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([ return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) + err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", hashedId) if err != nil { return *new(CapabilityRegistryCapability), err @@ -226,17 +226,17 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.Ca } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName [32]byte, version [32]byte) ([32]byte, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilityID", capabilityType, version) + err := _CapabilityRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) if err != nil { return *new([32]byte), err @@ -248,12 +248,12 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityID(opts *bind. } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +func (_CapabilityRegistry *CapabilityRegistrySession) GetHashedCapabilityId(labelledName [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetHashedCapabilityId(labelledName [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) } func (_CapabilityRegistry *CapabilityRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) { @@ -300,9 +300,9 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(node return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) } -func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", capabilityId) + err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) if err != nil { return *new(bool), err @@ -314,12 +314,12 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts } -func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) } func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { @@ -414,16 +414,16 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodes(nodes [ return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", capabilityId) +func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapability(hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapability(hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, hashedCapabilityId) } func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) { @@ -523,32 +523,32 @@ func (it *CapabilityRegistryCapabilityAddedIterator) Close() error { } type CapabilityRegistryCapabilityAdded struct { - CapabilityId [32]byte - Raw types.Log + HashedCapabilityId [32]byte + Raw types.Log } -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityAdded", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityAdded", hashedCapabilityIdRule) if err != nil { return nil, err } return &CapabilityRegistryCapabilityAddedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityAdded", logs: logs, sub: sub}, nil } -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityAdded", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityAdded", hashedCapabilityIdRule) if err != nil { return nil, err } @@ -650,32 +650,32 @@ func (it *CapabilityRegistryCapabilityDeprecatedIterator) Close() error { } type CapabilityRegistryCapabilityDeprecated struct { - CapabilityId [32]byte - Raw types.Log + HashedCapabilityId [32]byte + Raw types.Log } -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) if err != nil { return nil, err } return &CapabilityRegistryCapabilityDeprecatedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil } -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) if err != nil { return nil, err } @@ -1544,15 +1544,15 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { type CapabilityRegistryInterface interface { GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) - GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) + GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) - GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetHashedCapabilityId(opts *bind.CallOpts, labelledName [32]byte, version [32]byte) ([32]byte, error) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) - IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) + IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -1566,7 +1566,7 @@ type CapabilityRegistryInterface interface { AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) - DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) + DeprecateCapability(opts *bind.TransactOpts, hashedCapabilityId [32]byte) (*types.Transaction, error) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) @@ -1574,15 +1574,15 @@ type CapabilityRegistryInterface interface { UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) - FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) + FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) - WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) + WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) - FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) + FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) - WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) + WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 3e0110cdee6..182c8da3f7e 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin b7d748b585d7cf1cf91e268b609613f77a8390d119e03d724b49c25fd2ea75e7 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin aeb366351d69f320c610419a3e09a991bd6ea75690778835eb8f6421d1277f44 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 9629e845336..e405102e123 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -78,7 +78,7 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { // triggersInitialized := true for _, t := range e.workflow.triggers { - tg, err := e.registry.GetTrigger(ctx, t.Type) + tg, err := e.registry.GetTrigger(ctx, t.ID) if err != nil { e.logger.Errorf("failed to get trigger capability: %s", err) // we don't immediately return here, since we want to retry all triggers @@ -123,16 +123,16 @@ func (e *Engine) initializeCapability(ctx context.Context, s *step) error { return nil } - cp, err := e.registry.Get(ctx, s.Type) + cp, err := e.registry.Get(ctx, s.ID) if err != nil { - return fmt.Errorf("failed to get capability with ref %s: %s", s.Type, err) + return fmt.Errorf("failed to get capability with ref %s: %s", s.ID, err) } // We configure actions, consensus and targets here, and // they all satisfy the `CallbackCapability` interface cc, ok := cp.(capabilities.CallbackCapability) if !ok { - return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.Type) + return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.ID) } if s.config == nil { @@ -275,7 +275,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) erro } eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { - return fmt.Errorf("failed to instantiate trigger %s, %s", t.Type, err) + return fmt.Errorf("failed to instantiate trigger %s, %s", t.ID, err) } go func() { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 3896f840ee8..ff4c5682129 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -19,7 +19,7 @@ import ( const hardcodedWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -27,7 +27,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -49,14 +49,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - type: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia" inputs: report: "$(evm_median.outputs.report)" config: @@ -215,7 +215,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { const ( simpleWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -223,7 +223,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -245,7 +245,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: @@ -368,7 +368,7 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { const ( multiStepWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -376,14 +376,14 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD actions: - - type: "read_chain_action" + - id: "read_chain_action" ref: "read_chain_action" inputs: action: - "$(trigger.outputs)" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -406,7 +406,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index 92abf36d2c0..cd167403089 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -19,8 +19,7 @@ type stepRequest struct { // // Within the workflow spec, they are called "Capability Properties". type stepDefinition struct { - // TODO: Rename this, type here refers to the capability ID, not its type. - Type string `json:"type" jsonschema:"required"` + ID string `json:"id" jsonschema:"required"` Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` Inputs map[string]any `json:"inputs,omitempty"` Config map[string]any `json:"config" jsonschema:"required"` @@ -160,7 +159,7 @@ func Parse(yamlWorkflow string) (*workflow, error) { // To handle this, we default the `Ref` to the type, but ideally we // should find a better long-term way to handle this. if s.Ref == "" { - s.Ref = s.Type + s.Ref = s.ID } innerErr := g.AddVertex(&step{stepDefinition: s}) diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index 232e91eaaa8..0964b13d277 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -19,23 +19,23 @@ func TestParse_Graph(t *testing.T) { name: "basic example", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -58,28 +58,28 @@ targets: name: "circular relationship", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) output: $(a-second-action.outputs) - - type: "a-second-action" + - id: "a-second-action" ref: "a-second-action" inputs: output: $(an-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -90,32 +90,32 @@ targets: name: "indirect circular relationship", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(a-third-action.outputs) - - type: "a-second-action" + - id: "a-second-action" ref: "a-second-action" inputs: output: $(an-action.outputs) - - type: "a-third-action" + - id: "a-third-action" ref: "a-third-action" inputs: output: $(a-second-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -126,23 +126,23 @@ targets: name: "relationship doesn't exist", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(missing-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -153,23 +153,23 @@ targets: name: "two trigger nodes", yaml: ` triggers: - - type: "a-trigger" - - type: "a-second-trigger" + - id: "a-trigger" + - id: "a-second-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -191,21 +191,21 @@ targets: name: "non-trigger step with no dependent refs", yaml: ` triggers: - - type: "a-trigger" - - type: "a-second-trigger" + - id: "a-trigger" + - id: "a-second-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: hello: "world" consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 280a895f1b8..5ed7941f84a 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -166,17 +166,19 @@ func (m mapping) MarshalJSON() ([]byte, error) { // It allows for multiple ways of defining a step, which we later // convert to a single representation, `stepDefinition`. type stepDefinitionYaml struct { - // A universally unique name for a capability will be defined under the “type” property. The uniqueness will, eventually, be enforced in the Capability Registry . Semver must be used to specify the version of the Capability at the end of the type field. Capability versions must be immutable. + // A universally unique name for a capability will be defined under the “id” property. The uniqueness will, eventually, be enforced in the Capability Registry. + // + // Semver must be used to specify the version of the Capability at the end of the id field. Capability versions must be immutable. // // Initially, we will require major versions. This will ease upgrades early on while we develop the infrastructure. // // Eventually, we might support minor version and specific version pins. This will allow workflow authors to have flexibility when selecting the version, and node operators will be able to determine when they should update their capabilities. // - // There are two ways to specify a type - using a string as a fully qualified ID or a structured table. When using a table, labels are ordered alphanumerically and joined into a string following a + // There are two ways to specify an id - using a string as a fully qualified ID or a structured table. When using a table, labels are ordered alphanumerically and joined into a string following a // {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // pattern. // - // The “type” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. + // The “id” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. // // Validation must throw an error if: // @@ -184,11 +186,11 @@ type stepDefinitionYaml struct { // (For Keystone only.) More specific than a major version is specified. // // Example (string) - // type: read_chain:chain_ethereum:network_mainnet@1 + // id: read_chain:chain_ethereum:network_mainnet@1 // // Example (table) // - // type: + // id: // name: read_chain // version: 1 // labels: @@ -196,7 +198,7 @@ type stepDefinitionYaml struct { // network: mainnet // // [semver regex]: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string - Type stepDefinitionType `json:"type" jsonschema:"required"` + ID stepDefinitionID `json:"id" jsonschema:"required"` // Actions and Consensus capabilities have a required “ref” property that must be unique within a Workflow file (not universally) This property enables referencing outputs and is required because Actions and Consensus always need to be referenced in the following phases. Triggers can optionally specify if they need to be referenced. // @@ -213,7 +215,7 @@ type stepDefinitionYaml struct { // Capabilities can specify an additional optional ”inputs” property. It allows specifying a dependency on the result of one or more other capabilities. These are always runtime values that cannot be provided upfront. It takes a map of the argument name internal to the capability and an explicit reference to the values. // - // References are specified using the [type].[ref].[path_to_value] pattern. + // References are specified using the [id].[ref].[path_to_value] pattern. // // The interpolation of “inputs” is allowed // @@ -231,7 +233,7 @@ type stepDefinitionYaml struct { // // Example // targets: - // - type: write_polygon_mainnet@1 + // - id: write_polygon_mainnet@1 // inputs: // report: // - consensus.evm_median.outputs.report @@ -248,66 +250,66 @@ type stepDefinitionYaml struct { func (s stepDefinitionYaml) toStepDefinition() stepDefinition { return stepDefinition{ Ref: s.Ref, - Type: s.Type.String(), + ID: s.ID.String(), Inputs: s.Inputs, Config: s.Config, } } -// stepDefinitionType represents both the string and table representations of the "type" field in a stepDefinition. -type stepDefinitionType struct { - typeStr string - typeTable *stepDefinitionTableType +// stepDefinitionID represents both the string and table representations of the "id" field in a stepDefinition. +type stepDefinitionID struct { + idStr string + idTable *stepDefinitionTableID } -func (s stepDefinitionType) String() string { - if s.typeStr != "" { - return s.typeStr +func (s stepDefinitionID) String() string { + if s.idStr != "" { + return s.idStr } - return s.typeTable.String() + return s.idTable.String() } -func (s *stepDefinitionType) UnmarshalJSON(data []byte) error { +func (s *stepDefinitionID) UnmarshalJSON(data []byte) error { // Unmarshal the JSON data into a map to determine if it's a string or a table var m string err := json.Unmarshal(data, &m) if err == nil { - s.typeStr = m + s.idStr = m return nil } - // If the JSON data is a table, unmarshal it into a stepDefinitionTableType - var table stepDefinitionTableType + // If the JSON data is a table, unmarshal it into a stepDefinitionTableID + var table stepDefinitionTableID err = json.Unmarshal(data, &table) if err != nil { return err } - s.typeTable = &table + s.idTable = &table return nil } -func (s *stepDefinitionType) MarshalJSON() ([]byte, error) { - if s.typeStr != "" { - return json.Marshal(s.typeStr) +func (s *stepDefinitionID) MarshalJSON() ([]byte, error) { + if s.idStr != "" { + return json.Marshal(s.idStr) } - return json.Marshal(s.typeTable) + return json.Marshal(s.idTable) } -// JSONSchema returns the JSON schema for a stepDefinitionType. +// JSONSchema returns the JSON schema for a stepDefinitionID. // // The schema is a oneOf schema that allows either a string or a table. -func (stepDefinitionType) JSONSchema() *jsonschema.Schema { +func (stepDefinitionID) JSONSchema() *jsonschema.Schema { reflector := jsonschema.Reflector{DoNotReference: true, ExpandedStruct: true} - tableSchema := reflector.Reflect(&stepDefinitionTableType{}) + tableSchema := reflector.Reflect(&stepDefinitionTableID{}) stringSchema := &jsonschema.Schema{ - Type: "string", + ID: "string", Pattern: "^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", } return &jsonschema.Schema{ - Title: "type", + Title: "id", OneOf: []*jsonschema.Schema{ stringSchema, tableSchema, @@ -315,21 +317,21 @@ func (stepDefinitionType) JSONSchema() *jsonschema.Schema { } } -// stepDefinitionTableType is the structured representation of a stepDefinitionType. -type stepDefinitionTableType struct { +// stepDefinitionTableID is the structured representation of a stepDefinitionID. +type stepDefinitionTableID struct { Name string `json:"name"` Version string `json:"version" jsonschema:"pattern=(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"` Labels map[string]string `json:"labels"` } -// String returns the string representation of a stepDefinitionTableType. +// String returns the string representation of a stepDefinitionTableID. // // It follows the format: // // {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // // where labels are ordered alphanumerically. -func (s stepDefinitionTableType) String() string { +func (s stepDefinitionTableID) String() string { labels := make([]string, 0, len(s.Labels)) for k, v := range s.Labels { labels = append(labels, fmt.Sprintf("%s_%s", k, v)) diff --git a/core/services/workflows/models_yaml_test.go b/core/services/workflows/models_yaml_test.go index 2732f1b44c7..efcdaf6f332 100644 --- a/core/services/workflows/models_yaml_test.go +++ b/core/services/workflows/models_yaml_test.go @@ -116,7 +116,7 @@ func TestWorkflowSpecMarshalling(t *testing.T) { } }) - t.Run("Table and string capability type", func(t *testing.T) { + t.Run("Table and string capability id", func(t *testing.T) { workflowBytes := fixtureReader("workflow_2") spec := workflowSpecYaml{} diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml index cbd33f4a90e..9a9870af875 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml @@ -1,5 +1,5 @@ triggers: - - type: mercury-trigger@1 + - id: mercury-trigger@1 ref: report_data config: boolean_coercion: @@ -54,7 +54,7 @@ # no actions consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 inputs: observations: - triggers.report_data.outputs @@ -76,7 +76,7 @@ abi: "mercury_reports bytes[]" targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 inputs: report: - consensus.evm_median.outputs.report diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml index 50a598d0bc9..be40a91daa0 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml @@ -1,12 +1,12 @@ triggers: - - type: on_mercury_report@1 + - id: on_mercury_report@1 ref: report_data config: {} # no actions consensus: - - type: + - id: name: trigger_test version: "2" labels: @@ -19,7 +19,7 @@ - triggers.report_data.outputs targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 config: {} inputs: report: diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json index f4024e24267..000fa469218 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json @@ -1,14 +1,14 @@ { "triggers": [ { - "type": "on_mercury_report@1", + "id": "on_mercury_report@1", "ref": "report_data", "config": {} } ], "consensus": [ { - "type": "trigger_test:aaShouldBeFirst_true:chain_ethereum:network_mainnet@2", + "id": "trigger_test:aaShouldBeFirst_true:chain_ethereum:network_mainnet@2", "inputs": { "observations": [ "triggers.report_data.outputs" @@ -19,7 +19,7 @@ ], "targets": [ { - "type": "write_polygon_mainnet@1", + "id": "write_polygon_mainnet@1", "inputs": { "report": [ "consensus.evm_median.outputs.report" @@ -28,4 +28,4 @@ "config": {} } ] -} +} \ No newline at end of file diff --git a/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml index 67d6890c47b..b3c984e9892 100644 --- a/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml @@ -1,14 +1,14 @@ triggers: -- type: trigger_test@1 +- id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting=1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml index f8c7d20136e..cb2f424e981 100644 --- a/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml @@ -1,14 +1,14 @@ triggers: -- type: trigger_test@1 +- id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml index b45676388c5..2e41eeb9898 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml @@ -1,15 +1,15 @@ # Should fail since version is more specific than major triggers: - - type: trigger_test@1.0 + - id: trigger_test@1.0 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml index c2a1872b4cf..36cd5b68b6b 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml @@ -1,16 +1,16 @@ # Should fail since version is more specific than major triggers: - - type: trigger_test@1.0.0 + - id: trigger_test@1.0.0 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml index 83bdcc610ef..4579c2899b9 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml @@ -1,14 +1,14 @@ triggers: - - type: trigger_test@1 + - id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1-beta.1 + - id: offchain_reporting@1-beta.1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1-alpha+sha246er3 + - id: write_polygon_mainnet@1-alpha+sha246er3 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json index 83ecd42ecb9..7f257f7798d 100644 --- a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json +++ b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json @@ -6,15 +6,15 @@ "mapping": { "type": "object" }, - "stepDefinitionType": { + "stepDefinitionID": { "oneOf": [ { - "type": "string", + "$id": "string", "pattern": "^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" }, { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/smartcontractkit/chainlink/v2/core/services/workflows/step-definition-table-type", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/services/workflows/step-definition-table-id", "properties": { "name": { "type": "string" @@ -39,12 +39,12 @@ ] } ], - "title": "type" + "title": "id" }, "stepDefinitionYaml": { "properties": { - "type": { - "$ref": "#/$defs/stepDefinitionType" + "id": { + "$ref": "#/$defs/stepDefinitionID" }, "ref": { "type": "string", @@ -60,7 +60,7 @@ "additionalProperties": false, "type": "object", "required": [ - "type", + "id", "config" ] }, @@ -100,4 +100,4 @@ ] } } -} +} \ No newline at end of file diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index bade8fe293b..0146038d91b 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -397,7 +397,7 @@ func TestJobController_Create_HappyPath(t *testing.T) { owner := "00000000000000000000000000000000000000aa" workflow := ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -405,7 +405,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -427,14 +427,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - type: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia" inputs: report: "$(evm_median.outputs.report)" config: From 644f5f271d9ed47e999e1d9aa4b99e5de0fd8b89 Mon Sep 17 00:00:00 2001 From: Austin Born Date: Thu, 2 May 2024 05:47:42 -0700 Subject: [PATCH 04/35] Operator Forwarder Production Readiness (#12983) * move oepratorforwarder out of dev/ and add more test cases * Update test locations * Update gas snapshot * Update solc compile * Changeset * Prettier linting + hardhat test updates * Interface naming and test updates * Update Deployer.sol => Deployer.t.sol * Rework OperatorForwarder tests * Update gas snapshot * prettier * Fix Hardhat tests * More style maintenance * Update constant variables in Deployer.t.sol * Update gas snapshot --- .github/workflows/solidity-foundry.yml | 2 +- contracts/.changeset/small-paws-crash.md | 5 + contracts/GNUmakefile | 2 +- .../operatorforwarder.gas-snapshot | 23 +- .../native_solc_compile_all_operatorforwarder | 9 +- .../{dev => }/AuthorizedForwarder.sol | 2 +- .../{dev => }/AuthorizedReceiver.sol | 4 +- .../{dev => }/LinkTokenReceiver.sol | 0 .../operatorforwarder/{dev => }/Operator.sol | 24 +- .../{dev => }/OperatorFactory.sol | 0 .../operatorforwarder/dev/test/operator.t.sol | 100 ------ .../IAuthorizedReceiver.sol} | 2 +- .../IWithdrawal.sol} | 2 +- .../v0.8/operatorforwarder/test/Factory.t.sol | 69 +++++ .../operatorforwarder/test/Forwarder.t.sol | 183 +++++++++++ .../operatorforwarder/test/operator.t.sol | 291 ++++++++++++++++++ .../test/testhelpers/BasicConsumer.sol | 0 .../test/testhelpers/Callback.sol | 21 ++ .../testhelpers/ChainlinkClientHelper.sol | 6 +- .../test/testhelpers/Chainlinked.sol | 2 +- .../{dev => }/test/testhelpers/Consumer.sol | 12 +- .../test/testhelpers/Deployer.t.sol | 33 ++ .../test/testhelpers/EmptyOracle.sol | 4 +- .../test/testhelpers/GasGuzzlingConsumer.sol | 2 +- .../test/testhelpers/GetterSetter.sol | 24 +- .../test/testhelpers/MaliciousChainlink.sol | 4 +- .../test/testhelpers/MaliciousChainlinked.sol | 30 +- .../test/testhelpers/MaliciousConsumer.sol | 6 +- .../MaliciousMultiWordConsumer.sol | 4 +- .../test/testhelpers/MaliciousRequester.sol | 2 +- .../test/testhelpers/MockReceiver.sol | 18 ++ .../test/testhelpers/MultiWordConsumer.sol | 48 ++- contracts/test/v0.8/ChainlinkClient.test.ts | 6 +- .../AuthorizedForwarder.test.ts | 4 +- .../v0.8/operatorforwarder/Operator.test.ts | 34 +- .../operatorforwarder/OperatorFactory.test.ts | 6 +- 36 files changed, 774 insertions(+), 210 deletions(-) create mode 100644 contracts/.changeset/small-paws-crash.md rename contracts/src/v0.8/operatorforwarder/{dev => }/AuthorizedForwarder.sol (97%) rename contracts/src/v0.8/operatorforwarder/{dev => }/AuthorizedReceiver.sol (93%) rename contracts/src/v0.8/operatorforwarder/{dev => }/LinkTokenReceiver.sol (100%) rename contracts/src/v0.8/operatorforwarder/{dev => }/Operator.sol (96%) rename contracts/src/v0.8/operatorforwarder/{dev => }/OperatorFactory.sol (100%) delete mode 100644 contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol rename contracts/src/v0.8/operatorforwarder/{dev/interfaces/AuthorizedReceiverInterface.sol => interfaces/IAuthorizedReceiver.sol} (87%) rename contracts/src/v0.8/operatorforwarder/{dev/interfaces/WithdrawalInterface.sol => interfaces/IWithdrawal.sol} (93%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/Factory.t.sol create mode 100644 contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol create mode 100644 contracts/src/v0.8/operatorforwarder/test/operator.t.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/BasicConsumer.sol (100%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/ChainlinkClientHelper.sol (76%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/Chainlinked.sol (98%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/Consumer.sol (87%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/EmptyOracle.sol (83%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/GasGuzzlingConsumer.sol (96%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/GetterSetter.sol (71%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousChainlink.sol (91%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousChainlinked.sol (80%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousConsumer.sol (92%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousMultiWordConsumer.sol (94%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousRequester.sol (95%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MultiWordConsumer.sol (81%) diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 2d62ef864a5..5e2d95ea9d1 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - product: [vrf, automation, llo-feeds, l2ep, functions, keystone, shared] + product: [automation, functions, keystone, l2ep, llo-feeds, operatorforwarder, shared, vrf] needs: [changes] name: Foundry Tests ${{ matrix.product }} # See https://github.com/foundry-rs/foundry/issues/3827 diff --git a/contracts/.changeset/small-paws-crash.md b/contracts/.changeset/small-paws-crash.md new file mode 100644 index 00000000000..3a3efa36805 --- /dev/null +++ b/contracts/.changeset/small-paws-crash.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Update operatorforwarder tests and pull out of dev/ diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 4ec8057b975..ba11b396e89 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -1,6 +1,6 @@ # ALL_FOUNDRY_PRODUCTS contains a list of all products that have a foundry # profile defined and use the Foundry snapshots. -ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions keystone shared transmission +ALL_FOUNDRY_PRODUCTS = functions keystone l2ep llo-feeds operatorforwarder shared transmission # To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var # or call the target with `FOUNDRY_PROFILE=product` diff --git a/contracts/gas-snapshots/operatorforwarder.gas-snapshot b/contracts/gas-snapshots/operatorforwarder.gas-snapshot index 964c1a91b8d..ee6c063f2f3 100644 --- a/contracts/gas-snapshots/operatorforwarder.gas-snapshot +++ b/contracts/gas-snapshots/operatorforwarder.gas-snapshot @@ -1,2 +1,21 @@ -Operator_cancelRequest:test_Success(uint96) (runs: 256, μ: 306103, ~: 306096) -Operator_cancelRequest:test_afterSuccessfulRequestSucess(uint96) (runs: 256, μ: 384781, ~: 389554) \ No newline at end of file +FactoryTest:test_DeployNewForwarderAndTransferOwnership_Success() (gas: 1059722) +FactoryTest:test_DeployNewForwarder_Success() (gas: 1048209) +FactoryTest:test_DeployNewOperatorAndForwarder_Success() (gas: 4069305) +FactoryTest:test_DeployNewOperator_Success() (gas: 3020464) +ForwarderTest:test_Forward_Success(uint256) (runs: 256, μ: 226200, ~: 227289) +ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 256, μ: 257876, ~: 259120) +ForwarderTest:test_OwnerForward_Success() (gas: 30118) +ForwarderTest:test_SetAuthorizedSenders_Success() (gas: 160524) +ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35123) +OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) +OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) +OperatorTest:test_OracleRequest_Success() (gas: 250019) +OperatorTest:test_OracleRequest_Success() (gas: 250019) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) +OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303620) +OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303620) \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_operatorforwarder b/contracts/scripts/native_solc_compile_all_operatorforwarder index 2d455994813..c791d50c1d6 100755 --- a/contracts/scripts/native_solc_compile_all_operatorforwarder +++ b/contracts/scripts/native_solc_compile_all_operatorforwarder @@ -28,8 +28,9 @@ compileContract () { } # Contracts -compileContract operatorforwarder/dev/AuthorizedForwarder.sol -compileContract operatorforwarder/dev/AuthorizedReceiver.sol -compileContract operatorforwarder/dev/Operator.sol -compileContract operatorforwarder/dev/OperatorFactory.sol +compileContract operatorforwarder/AuthorizedForwarder.sol +compileContract operatorforwarder/AuthorizedReceiver.sol +compileContract operatorforwarder/LinkTokenReceiver.sol +compileContract operatorforwarder/Operator.sol +compileContract operatorforwarder/OperatorFactory.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol b/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol similarity index 97% rename from contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol rename to contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol index 824ffce6f0f..ffb09248701 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol +++ b/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ConfirmedOwnerWithProposal} from "../../shared/access/ConfirmedOwnerWithProposal.sol"; +import {ConfirmedOwnerWithProposal} from "../shared/access/ConfirmedOwnerWithProposal.sol"; import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; diff --git a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol b/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol similarity index 93% rename from contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol rename to contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol index b741118895f..919602b5acf 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol +++ b/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; // solhint-disable gas-custom-errors -abstract contract AuthorizedReceiver is AuthorizedReceiverInterface { +abstract contract AuthorizedReceiver is IAuthorizedReceiver { mapping(address sender => bool authorized) private s_authorizedSenders; address[] private s_authorizedSenderList; diff --git a/contracts/src/v0.8/operatorforwarder/dev/LinkTokenReceiver.sol b/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/LinkTokenReceiver.sol rename to contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol b/contracts/src/v0.8/operatorforwarder/Operator.sol similarity index 96% rename from contracts/src/v0.8/operatorforwarder/dev/Operator.sol rename to contracts/src/v0.8/operatorforwarder/Operator.sol index e68df5fd075..64882e43cda 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol +++ b/contracts/src/v0.8/operatorforwarder/Operator.sol @@ -3,19 +3,19 @@ pragma solidity 0.8.19; import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; import {LinkTokenReceiver} from "./LinkTokenReceiver.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol"; -import {OperatorInterface} from "../../interfaces/OperatorInterface.sol"; -import {IOwnable} from "../../shared/interfaces/IOwnable.sol"; -import {WithdrawalInterface} from "./interfaces/WithdrawalInterface.sol"; -import {OracleInterface} from "../../interfaces/OracleInterface.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; +import {OperatorInterface} from "../interfaces/OperatorInterface.sol"; +import {IOwnable} from "../shared/interfaces/IOwnable.sol"; +import {IWithdrawal} from "./interfaces/IWithdrawal.sol"; +import {OracleInterface} from "../interfaces/OracleInterface.sol"; +import {SafeCast} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; // @title The Chainlink Operator contract // @notice Node operators can deploy this contract to fulfill requests sent to them // solhint-disable gas-custom-errors -contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, WithdrawalInterface { +contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, IWithdrawal { struct Commitment { bytes31 paramsHash; uint8 dataVersion; @@ -241,7 +241,7 @@ contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, Oper emit TargetsUpdatedAuthorizedSenders(targets, senders, msg.sender); for (uint256 i = 0; i < targets.length; ++i) { - AuthorizedReceiverInterface(targets[i]).setAuthorizedSenders(senders); + IAuthorizedReceiver(targets[i]).setAuthorizedSenders(senders); } } @@ -266,14 +266,14 @@ contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, Oper function withdraw( address recipient, uint256 amount - ) external override(OracleInterface, WithdrawalInterface) onlyOwner validateAvailableFunds(amount) { + ) external override(OracleInterface, IWithdrawal) onlyOwner validateAvailableFunds(amount) { assert(i_linkToken.transfer(recipient, amount)); } // @notice Displays the amount of LINK that is available for the node operator to withdraw // @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage // @return The amount of withdrawable LINK on the contract - function withdrawable() external view override(OracleInterface, WithdrawalInterface) returns (uint256) { + function withdrawable() external view override(OracleInterface, IWithdrawal) returns (uint256) { return _fundsAvailable(); } diff --git a/contracts/src/v0.8/operatorforwarder/dev/OperatorFactory.sol b/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/OperatorFactory.sol rename to contracts/src/v0.8/operatorforwarder/OperatorFactory.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol b/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol deleted file mode 100644 index 96975a2baf4..00000000000 --- a/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {Operator} from "../Operator.sol"; -import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; -import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; - -contract Operator_cancelRequest is Test { - address public s_link; - ChainlinkClientHelper public s_client; - Operator public s_operator; - - function setUp() public { - s_link = address(new LinkToken()); - s_client = new ChainlinkClientHelper(s_link); - - address[] memory auth = new address[](1); - auth[0] = address(this); - s_operator = new Operator(s_link, address(this)); - s_operator.setAuthorizedSenders(auth); - } - - function test_Success(uint96 payment) public { - payment = uint96(bound(payment, 1, type(uint96).max)); - deal(s_link, address(s_client), payment); - // We're going to cancel one request and fulfil the other - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // 1 payment in escrow - // Client has zero link - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation. - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), payment); - } - - function test_afterSuccessfulRequestSucess(uint96 payment) public { - payment = uint96(bound(payment, 1, type(uint96).max) / 2); - deal(s_link, address(s_client), 2 * payment); - - // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 2 * payment); - - // We're going to cancel one request and fulfil the other - bytes32 requestId = s_client.sendRequest(address(s_operator), payment); - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // Operator now has the 2 payments in escrow - // Client has zero payments - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 2 * payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Fulfill one request - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - s_operator.fulfillOracleRequest( - requestId, - payment, - address(s_client), - s_client.FULFILSELECTOR(), - expiration, - bytes32(hex"01") - ); - // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow - assertEq(s_operator.withdrawable(), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 2 * payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable - assertEq(s_operator.withdrawable(), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), payment); - - // Withdraw the remaining payment - s_operator.withdraw(address(s_client), payment); - - // End state is exactly the same as the initial state. - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 2 * payment); - } -} diff --git a/contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol similarity index 87% rename from contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol index 28b20b14f33..78140d58682 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol +++ b/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface AuthorizedReceiverInterface { +interface IAuthorizedReceiver { function isAuthorizedSender(address sender) external view returns (bool); function getAuthorizedSenders() external returns (address[] memory); diff --git a/contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol similarity index 93% rename from contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol index c064b0627b5..433738d406f 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol +++ b/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface WithdrawalInterface { +interface IWithdrawal { // @notice transfer LINK held by the contract belonging to msg.sender to // another address // @param recipient is the address to send the LINK to diff --git a/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol b/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol new file mode 100644 index 00000000000..d54dc620460 --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; +import {Operator} from "../Operator.sol"; + +contract FactoryTest is Deployer { + function setUp() public { + _setUp(); + + vm.startPrank(ALICE); + } + + function test_DeployNewOperator_Success() public { + // Deploy a new operator using the factory. + address newOperator = s_factory.deployNewOperator(); + // Assert that the new operator was indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + } + + function test_DeployNewOperatorAndForwarder_Success() public { + // Deploy both a new operator and a new forwarder using the factory. + (address newOperator, address newForwarder) = s_factory.deployNewOperatorAndForwarder(); + + // Assert that the new operator and the new forwarder were indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + + //Operator to accept ownership + vm.startPrank(newOperator); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + // Ensure that the newly deployed operator is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == newOperator, "operator is not the owner"); + } + + function test_DeployNewForwarder_Success() public { + // Deploy a new forwarder using the factory. + address newForwarder = s_factory.deployNewForwarder(); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + } + + function test_DeployNewForwarderAndTransferOwnership_Success() public { + // Deploy a new forwarder with a proposal to transfer its ownership to Bob. + address newForwarder = s_factory.deployNewForwarderAndTransferOwnership(BOB, new bytes(0)); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is still the current owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + + // Only proposed owner can call acceptOwnership() + vm.expectRevert("Must be proposed owner"); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + vm.startPrank(BOB); + // Let Bob accept the ownership. + AuthorizedForwarder(newForwarder).acceptOwnership(); + // Ensure that Bob is now the owner of the forwarder after the transfer. + require(AuthorizedForwarder(newForwarder).owner() == BOB); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol b/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol new file mode 100644 index 00000000000..ba6ce1c17c1 --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; + +contract ForwarderTest is Deployer { + AuthorizedForwarder internal s_forwarder; + + function setUp() public { + _setUp(); + + vm.prank(ALICE); + s_forwarder = AuthorizedForwarder(s_factory.deployNewForwarder()); + } + + function test_SetAuthorizedSenders_Success() public { + address[] memory senders; + + // Expect a revert when trying to set an empty list of authorized senders + vm.expectRevert("Cannot set authorized senders"); + s_forwarder.setAuthorizedSenders(senders); + + vm.prank(ALICE); + // Expect a revert because the sender list is empty + vm.expectRevert("Must have at least 1 sender"); + s_forwarder.setAuthorizedSenders(senders); + + // Create a list with two identical sender addresses + senders = new address[](2); + senders[0] = SENDER_1; + senders[1] = SENDER_1; + + vm.prank(ALICE); + // Expect a revert because the sender list has duplicates + vm.expectRevert("Must not have duplicate senders"); + s_forwarder.setAuthorizedSenders(senders); + + // Set the second sender to a different address + senders[1] = SENDER_2; + + vm.prank(ALICE); + // Update the authorized senders list + s_forwarder.setAuthorizedSenders(senders); + + // Check if both SENDER_1 and SENDER_2 are now authorized + assertTrue(s_forwarder.isAuthorizedSender(SENDER_1)); + assertTrue(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Fetch the authorized senders and verify they match the set addresses + address[] memory returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + require(returnedSenders[1] == senders[1]); + + // Create a new list with only SENDER_3 + senders = new address[](1); + senders[0] = SENDER_3; + + // Prank 'alice' and update the authorized senders to just SENDER_3 + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + + // Ensure SENDER_1 and SENDER_2 are no longer authorized + assertFalse(s_forwarder.isAuthorizedSender(SENDER_1)); + assertFalse(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Check that SENDER_3 is now the only authorized sender + assertTrue(s_forwarder.isAuthorizedSender(SENDER_3)); + returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + } + + function test_Forward_Success(uint256 _value) public { + _addSenders(); + + vm.expectRevert("Not authorized sender"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.forward(address(s_link), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.forward(address(s_mockReceiver), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("test revert message"); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("revertMessage()")); + + vm.prank(SENDER_1); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("receiveData(uint256)", _value)); + + require(s_mockReceiver.getValue() == _value); + } + + function test_MultiForward_Success(uint256 _value1, uint256 _value2) public { + _addSenders(); + + address[] memory tos; + bytes[] memory datas; + + vm.expectRevert("Not authorized sender"); + s_forwarder.multiForward(tos, datas); + + tos = new address[](2); + datas = new bytes[](1); + + vm.prank(SENDER_1); + vm.expectRevert("Arrays must have the same length"); + s_forwarder.multiForward(tos, datas); + + datas = new bytes[](2); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.multiForward(tos, datas); + + tos[0] = address(s_mockReceiver); + tos[1] = address(s_link); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.multiForward(tos, datas); + + datas[0] = abi.encodeWithSignature("receiveData(uint256)", _value1); + datas[1] = abi.encodeWithSignature("receiveData(uint256)", _value2); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.multiForward(tos, datas); + + tos[1] = address(s_mockReceiver); + + vm.prank(SENDER_1); + s_forwarder.multiForward(tos, datas); + + require(s_mockReceiver.getValue() == _value2); + } + + function test_OwnerForward_Success() public { + vm.expectRevert("Only callable by owner"); + s_forwarder.ownerForward(address(0), new bytes(0)); + + vm.prank(ALICE); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.ownerForward(address(s_link), new bytes(0)); + + vm.prank(ALICE); + s_forwarder.ownerForward(address(s_link), abi.encodeWithSignature("balanceOf(address)", address(0))); + } + + function test_TransferOwnershipWithMessage_Success() public { + vm.prank(BOB); + vm.expectRevert("Only callable by owner"); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.prank(ALICE); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.expectRevert("Must be proposed owner"); + s_forwarder.acceptOwnership(); + + vm.prank(BOB); + s_forwarder.acceptOwnership(); + + require(s_forwarder.owner() == BOB); + } + + function _addSenders() internal { + address[] memory senders = new address[](3); + senders[0] = SENDER_1; + senders[1] = SENDER_2; + senders[2] = SENDER_3; + + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/test/operator.t.sol b/contracts/src/v0.8/operatorforwarder/test/operator.t.sol new file mode 100644 index 00000000000..6c4a7c2ae1a --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/operator.t.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Operator} from "../Operator.sol"; +import {Callback} from "./testhelpers/Callback.sol"; +import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; +import {Deployer} from "./testhelpers/Deployer.t.sol"; + +contract OperatorTest is Deployer { + ChainlinkClientHelper private s_client; + Callback private s_callback; + Operator private s_operator; + + function setUp() public { + _setUp(); + s_client = new ChainlinkClientHelper(address(s_link)); + + address[] memory auth = new address[](1); + auth[0] = address(this); + s_operator = new Operator(address(s_link), address(this)); + s_operator.setAuthorizedSenders(auth); + + s_callback = new Callback(address(s_operator)); + } + + function test_SendRequest_Success(uint96 payment) public { + vm.assume(payment > 0); + deal(address(s_link), address(s_client), payment); + // We're going to cancel one request and fulfill the other + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // 1 payment in escrow + // Client has zero link + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), payment); + } + + function test_SendRequestAndCancelRequest_Success(uint96 payment) public { + vm.assume(payment > 1); + payment /= payment; + + deal(address(s_link), address(s_client), 2 * payment); + + // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + + // We're going to cancel one request and fulfill the other + bytes32 requestId = s_client.sendRequest(address(s_operator), payment); + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // Operator now has the 2 payments in escrow + // Client has zero payments + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Fulfill one request + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_client), + s_client.FULFILL_SELECTOR(), + expiration, + bytes32(hex"01") + ); + // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), payment); + + // Withdraw the remaining payment + s_operator.withdraw(address(s_client), payment); + + // End state is exactly the same as the initial state. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + } + + function test_OracleRequest_Success() public { + // Define some mock values + bytes32 specId = keccak256("testSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 0; + uint256 dataVersion = 1; + bytes memory data = ""; + + uint256 initialLinkBalance = s_link.balanceOf(address(s_operator)); + uint256 payment = 1 ether; // Mock payment value + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), ALICE, payment); + assertEq(s_link.balanceOf(ALICE), 1 ether, "balance update failed"); + + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + data + ) + ); + + // Check that the LINK tokens were transferred to the Operator contract + assertEq(s_link.balanceOf(address(s_operator)), initialLinkBalance + payment); + // No withdrawable LINK as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore); + } + + function test_FulfillOracleRequest_Success() public { + // This test file is the callback target and actual sender contract + // so we should enable it to set Authorised senders to itself + address[] memory senders = new address[](2); + senders[0] = address(this); + senders[0] = BOB; + + s_operator.setAuthorizedSenders(senders); + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForFulfill"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 1; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + // Convert bytes to bytes32 + bytes32 data = bytes32(keccak256(dataBytes)); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // Fulfill the request using the operator + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + vm.prank(BOB); + s_operator.fulfillOracleRequest(requestId, payment, address(s_callback), callbackFunctionId, expiration, data); + + assertEq(s_callback.getCallbacksReceived(), 1, "Oracle request was not fulfilled"); + + // Withdrawable balance + assertEq(s_operator.withdrawable(), withdrawableBefore + payment, "Internal accounting not updated correctly"); + } + + function test_CancelOracleRequest_Success() public { + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForCancel"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 2; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + BOB, + payment, + specId, + BOB, + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // No withdrawable balance as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + + vm.startPrank(ALICE); + vm.expectRevert(bytes("Params do not match request ID")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.startPrank(BOB); + vm.expectRevert(bytes("Request is not expired")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.warp(expiration); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + // Check if the LINK tokens were refunded to the sender (bob in this case) + assertEq(s_link.balanceOf(BOB), 1 ether, "Oracle request was not canceled properly"); + + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + } + + function test_NotAuthorizedSender_Revert() public { + bytes32 specId = keccak256("unauthorizedFulfillSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 5; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + deal(address(s_link), ALICE, payment); + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + ALICE, + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + bytes32 requestId = keccak256(abi.encodePacked(ALICE, nonce)); + + vm.prank(BOB); + vm.expectRevert(bytes("Not authorized sender")); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_callback), + callbackFunctionId, + expiration, + bytes32(keccak256(dataBytes)) + ); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol new file mode 100644 index 00000000000..9dccfed428a --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract Callback { + address private s_operator; + uint256 private s_callbacksReceived = 0; + + constructor(address _operator) { + s_operator = _operator; + } + + // Callback function for oracle request fulfillment + function callback(bytes32) public { + require(msg.sender == s_operator, "Only Operator can call this function"); + s_callbacksReceived += 1; + } + + function getCallbacksReceived() public view returns (uint256) { + return s_callbacksReceived; + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol similarity index 76% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol index d15eb07c8c9..9b6ba6bb432 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient} from "../../../../ChainlinkClient.sol"; +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; contract ChainlinkClientHelper is ChainlinkClient { - bytes4 public constant FULFILSELECTOR = this.fulfill.selector; + bytes4 public constant FULFILL_SELECTOR = this.fulfill.selector; constructor(address link) { _setChainlinkToken(link); } function sendRequest(address op, uint256 payment) external returns (bytes32) { - return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILSELECTOR), payment); + return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILL_SELECTOR), payment); } function cancelRequest(bytes32 requestId, uint256 payment, uint256 expiration) external { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol similarity index 98% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol index 86dc474e8a6..dba5d407623 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import {ChainlinkClient, Chainlink} from "../../../../ChainlinkClient.sol"; +import {ChainlinkClient, Chainlink} from "../../../ChainlinkClient.sol"; /** * @title The Chainlinked contract diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol similarity index 87% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol index 0d01778e19e..82709d3def8 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract Consumer is ChainlinkClient { using Chainlink for Chainlink.Request; bytes32 internal s_specId; - bytes32 public currentPrice; + bytes32 internal s_currentPrice; event RequestFulfilled( bytes32 indexed requestId, // User-defined ID @@ -50,6 +50,10 @@ contract Consumer is ChainlinkClient { function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { emit RequestFulfilled(_requestId, _price); - currentPrice = _price; + s_currentPrice = _price; + } + + function getCurrentPrice() public view returns (bytes32) { + return s_currentPrice; } } diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol new file mode 100644 index 00000000000..da746c7ff8c --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +import {MockReceiver} from "./MockReceiver.sol"; +import {AuthorizedForwarder} from "../../AuthorizedForwarder.sol"; +import {Operator} from "../../Operator.sol"; +import {OperatorFactory} from "../../OperatorFactory.sol"; +import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; + +abstract contract Deployer is Test { + OperatorFactory internal s_factory; + LinkToken internal s_link; + MockReceiver internal s_mockReceiver; + + address internal constant ALICE = address(0x101); + address internal constant BOB = address(0x102); + address internal constant SENDER_1 = address(0x103); + address internal constant SENDER_2 = address(0x104); + address internal constant SENDER_3 = address(0x105); + + function _setUp() internal { + _deploy(); + } + + function _deploy() internal { + s_link = new LinkToken(); + s_factory = new OperatorFactory(address(s_link)); + + s_mockReceiver = new MockReceiver(); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol similarity index 83% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol index 2abe393151e..f278791d2bb 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkRequestInterface} from "../../../../interfaces/ChainlinkRequestInterface.sol"; -import {OracleInterface} from "../../../../interfaces/OracleInterface.sol"; +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; +import {OracleInterface} from "../../../interfaces/OracleInterface.sol"; /* solhint-disable no-empty-blocks */ contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol similarity index 96% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol index 54ff0e30e66..029102018b0 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {Consumer} from "./Consumer.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract GasGuzzlingConsumer is Consumer { using Chainlink for Chainlink.Request; diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol similarity index 71% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol index 494da582e1b..722362bc4aa 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol @@ -3,10 +3,10 @@ pragma solidity ^0.8.0; // GetterSetter is a contract to aid debugging and testing during development. // solhint-disable contract GetterSetter { - bytes32 public getBytes32; - uint256 public getUint256; - bytes32 public requestId; - bytes public getBytes; + bytes32 private s_getBytes32; + uint256 private s_getUint256; + bytes32 private s_requestId; + bytes private s_getBytes; event SetBytes32(address indexed from, bytes32 indexed value); event SetUint256(address indexed from, uint256 indexed value); @@ -15,32 +15,36 @@ contract GetterSetter { event Output(bytes32 b32, uint256 u256, bytes32 b322); function setBytes32(bytes32 _value) public { - getBytes32 = _value; + s_getBytes32 = _value; emit SetBytes32(msg.sender, _value); } function requestedBytes32(bytes32 _requestId, bytes32 _value) public { - requestId = _requestId; + s_requestId = _requestId; setBytes32(_value); } function setBytes(bytes memory _value) public { - getBytes = _value; + s_getBytes = _value; emit SetBytes(msg.sender, _value); } + function getBytes() public view returns (bytes memory _value) { + return s_getBytes; + } + function requestedBytes(bytes32 _requestId, bytes memory _value) public { - requestId = _requestId; + s_requestId = _requestId; setBytes(_value); } function setUint256(uint256 _value) public { - getUint256 = _value; + s_getUint256 = _value; emit SetUint256(msg.sender, _value); } function requestedUint256(bytes32 _requestId, uint256 _value) public { - requestId = _requestId; + s_requestId = _requestId; setUint256(_value); } } diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol similarity index 91% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol index 5cc343aa7f4..11c863fbb98 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.0; -import {CBORChainlink as CBOR_Chainlink} from "../../../../vendor/CBORChainlink.sol"; -import {BufferChainlink as Buffer_Chainlink} from "../../../../vendor/BufferChainlink.sol"; +import {CBORChainlink as CBOR_Chainlink} from "../../../vendor/CBORChainlink.sol"; +import {BufferChainlink as Buffer_Chainlink} from "../../../vendor/BufferChainlink.sol"; // solhint-disable library MaliciousChainlink { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol similarity index 80% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol index 722fbdd599b..989c39c18be 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {MaliciousChainlink} from "./MaliciousChainlink.sol"; import {Chainlinked, Chainlink} from "./Chainlinked.sol"; -import {LinkTokenInterface} from "../../../../shared/interfaces/LinkTokenInterface.sol"; +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; // solhint-disable contract MaliciousChainlinked is Chainlinked { @@ -10,8 +10,8 @@ contract MaliciousChainlinked is Chainlinked { using MaliciousChainlink for MaliciousChainlink.WithdrawRequest; using Chainlink for Chainlink.Request; - uint256 private maliciousRequests = 1; - mapping(bytes32 => address) private maliciousPendingRequests; + uint256 private s_maliciousRequests = 1; + mapping(bytes32 => address) private s_maliciousPendingRequests; function newWithdrawRequest( bytes32 _specId, @@ -27,31 +27,31 @@ contract MaliciousChainlinked is Chainlinked { Chainlink.Request memory _req, uint256 _amount ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(_target, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(_target, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _amount, encodeTargetRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } function chainlinkPriceRequest(Chainlink.Request memory _req, uint256 _amount) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _amount, encodePriceRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } @@ -60,16 +60,16 @@ contract MaliciousChainlinked is Chainlinked { MaliciousChainlink.WithdrawRequest memory _req, uint256 _wei ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _wei, encodeWithdrawRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol similarity index 92% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol index 003e628880f..842eec90542 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol @@ -5,7 +5,7 @@ import {Chainlinked, Chainlink} from "./Chainlinked.sol"; // solhint-disable contract MaliciousConsumer is Chainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; - uint256 private expiration; + uint256 private s_expiration; constructor(address _link, address _oracle) public payable { setLinkToken(_link); @@ -16,7 +16,7 @@ contract MaliciousConsumer is Chainlinked { function requestData(bytes32 _id, bytes memory _callbackFunc) public { Chainlink.Request memory req = newRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); - expiration = block.timestamp + 5 minutes; + s_expiration = block.timestamp + 5 minutes; chainlinkRequest(req, ORACLE_PAYMENT); } @@ -25,7 +25,7 @@ contract MaliciousConsumer is Chainlinked { } function cancelRequestOnFulfill(bytes32 _requestId, bytes32) public { - _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, expiration); + _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); } function remove() public { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol similarity index 94% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol index 272361f2dda..d9d14cb3d43 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract MaliciousMultiWordConsumer is ChainlinkClient { uint256 private constant ORACLE_PAYMENT = 1 ether; diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol similarity index 95% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol index 9b19653722c..c01c8a60bb7 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {MaliciousChainlink} from "./MaliciousChainlink.sol"; import {MaliciousChainlinked, Chainlink} from "./MaliciousChainlinked.sol"; -import {ChainlinkRequestInterface} from "../../../../interfaces/ChainlinkRequestInterface.sol"; +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; contract MaliciousRequester is MaliciousChainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol new file mode 100644 index 00000000000..4e825b4505f --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract MockReceiver { + uint256 private s_value; + + function receiveData(uint256 _value) public { + s_value = _value; + } + + function revertMessage() public pure { + revert("test revert message"); + } + + function getValue() external view returns (uint256) { + return s_value; + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol similarity index 81% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol index ce2bf1907c5..fe249831fef 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol @@ -1,21 +1,21 @@ pragma solidity ^0.8.0; -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract MultiWordConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; bytes32 internal s_specId; - bytes public currentPrice; + bytes internal s_currentPrice; - bytes32 public usd; - bytes32 public eur; - bytes32 public jpy; + bytes32 private s_usd; + bytes32 private s_eur; + bytes32 private s_jpy; - uint256 public usdInt; - uint256 public eurInt; - uint256 public jpyInt; + uint256 private s_usdInt; + uint256 private s_eurInt; + uint256 private s_jpyInt; event RequestFulfilled( bytes32 indexed requestId, // User-defined ID @@ -100,9 +100,9 @@ contract MultiWordConsumer is ChainlinkClient { bytes32 _jpy ) public recordChainlinkFulfillment(_requestId) { emit RequestMultipleFulfilled(_requestId, _usd, _eur, _jpy); - usd = _usd; - eur = _eur; - jpy = _jpy; + s_usd = _usd; + s_eur = _eur; + s_jpy = _jpy; } function fulfillMultipleParametersWithCustomURLs( @@ -112,17 +112,33 @@ contract MultiWordConsumer is ChainlinkClient { uint256 _jpy ) public recordChainlinkFulfillment(_requestId) { emit RequestMultipleFulfilledWithCustomURLs(_requestId, _usd, _eur, _jpy); - usdInt = _usd; - eurInt = _eur; - jpyInt = _jpy; + s_usdInt = _usd; + s_eurInt = _eur; + s_jpyInt = _jpy; } function fulfillBytes(bytes32 _requestId, bytes memory _price) public recordChainlinkFulfillment(_requestId) { emit RequestFulfilled(_requestId, _price); - currentPrice = _price; + s_currentPrice = _price; } function publicGetNextRequestCount() external view returns (uint256) { return _getNextRequestCount(); } + + function getCurrentPrice() public view returns (bytes memory _value) { + return s_currentPrice; + } + + function usd() public view returns (bytes32 _value) { + return s_usd; + } + + function eur() public view returns (bytes32 _value) { + return s_eur; + } + + function jpy() public view returns (bytes32 _value) { + return s_jpy; + } } diff --git a/contracts/test/v0.8/ChainlinkClient.test.ts b/contracts/test/v0.8/ChainlinkClient.test.ts index b483e890a6b..c5691211c1a 100644 --- a/contracts/test/v0.8/ChainlinkClient.test.ts +++ b/contracts/test/v0.8/ChainlinkClient.test.ts @@ -27,15 +27,15 @@ before(async () => { roles.defaultAccount, ) emptyOracleFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol:EmptyOracle', + 'src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol:EmptyOracle', roles.defaultAccount, ) getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', roles.defaultAccount, ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', roles.defaultAccount, ) linkTokenFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts index 2d6329e221d..d4e1918c976 100644 --- a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts +++ b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts @@ -18,7 +18,7 @@ before(async () => { roles = users.roles getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', roles.defaultAccount, ) brokenFactory = await ethers.getContractFactory( @@ -26,7 +26,7 @@ before(async () => { roles.defaultAccount, ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', roles.defaultAccount, ) linkTokenFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/operatorforwarder/Operator.test.ts b/contracts/test/v0.8/operatorforwarder/Operator.test.ts index 0d75d8530a4..6fb8768f54a 100644 --- a/contracts/test/v0.8/operatorforwarder/Operator.test.ts +++ b/contracts/test/v0.8/operatorforwarder/Operator.test.ts @@ -50,31 +50,31 @@ before(async () => { roles = users.roles basicConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol:BasicConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol:BasicConsumer', ) multiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol:MultiWordConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol:MultiWordConsumer', ) gasGuzzlingConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', ) getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', ) maliciousRequesterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol:MaliciousRequester', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol:MaliciousRequester', ) maliciousConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol:MaliciousConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol:MaliciousConsumer', ) maliciousMultiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', ) linkTokenFactory = await ethers.getContractFactory( 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', @@ -1076,7 +1076,7 @@ describe('Operator', () => { .connect(roles.oracleNode) .fulfillOracleRequest(...convertFufillParams(request, response)) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal(response, ethers.utils.parseBytes32String(currentValue)) }) @@ -1105,7 +1105,7 @@ describe('Operator', () => { .fulfillOracleRequest(...convertFufillParams(request, response2)), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal(response, ethers.utils.parseBytes32String(currentValue)) }) }) @@ -1419,7 +1419,7 @@ describe('Operator', () => { }) describe('#fulfillOracleRequest2', () => { - describe('single word fulfils', () => { + describe('single word fulfills', () => { const response = 'Hi mom!' const responseTypes = ['bytes32'] const responseValues = [toBytes32String(response)] @@ -1528,7 +1528,7 @@ describe('Operator', () => { ), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal( response, ethers.utils.parseBytes32String(currentValue), @@ -1576,7 +1576,7 @@ describe('Operator', () => { ), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal( response, ethers.utils.parseBytes32String(currentValue), @@ -2024,7 +2024,7 @@ describe('Operator', () => { }) }) - describe('multi word fulfils', () => { + describe('multi word fulfills', () => { describe('one bytes parameter', () => { const response = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\ @@ -2149,7 +2149,7 @@ describe('Operator', () => { ), ) - const currentValue = await multiConsumer.currentPrice() + const currentValue = await multiConsumer.getCurrentPrice() assert.equal(response, ethers.utils.toUtf8String(currentValue)) }) @@ -2195,7 +2195,7 @@ describe('Operator', () => { ), ) - const currentValue = await multiConsumer.currentPrice() + const currentValue = await multiConsumer.getCurrentPrice() assert.equal(response, ethers.utils.toUtf8String(currentValue)) }) }) diff --git a/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts b/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts index b9a0fe508b0..b54a75c2c0d 100644 --- a/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts +++ b/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts @@ -20,15 +20,15 @@ before(async () => { roles.defaultAccount, ) operatorGeneratorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/OperatorFactory.sol:OperatorFactory', + 'src/v0.8/operatorforwarder/OperatorFactory.sol:OperatorFactory', roles.defaultAccount, ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', roles.defaultAccount, ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', roles.defaultAccount, ) }) From 8cf34d2d91bf92aeb373f349e5fc5aaf73111e3e Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 09:10:33 -0400 Subject: [PATCH 05/35] Autogen solidity wrappers (#13062) --- .../detect-solidity-file-changes/action.yml | 36 ++++++++ .github/workflows/solidity-wrappers.yml | 82 +++++++++++++++++++ .github/workflows/solidity.yml | 33 +------- 3 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 .github/actions/detect-solidity-file-changes/action.yml create mode 100644 .github/workflows/solidity-wrappers.yml diff --git a/.github/actions/detect-solidity-file-changes/action.yml b/.github/actions/detect-solidity-file-changes/action.yml new file mode 100644 index 00000000000..37cb871d68d --- /dev/null +++ b/.github/actions/detect-solidity-file-changes/action.yml @@ -0,0 +1,36 @@ +name: 'Detect Changes Composite Action' +description: 'Detects changes in solidity files and fails if read-only files are modified.' +outputs: + changes: + description: 'Whether or not changes were detected' + value: ${{ steps.changed_files.outputs.src }} +runs: + using: 'composite' + steps: + + - name: Filter paths + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changed_files + with: + list-files: 'csv' + filters: | + src: + - 'contracts/**/*' + - '.github/workflows/solidity.yml' + - '.github/workflows/solidity-foundry.yml' + - '.github/workflows/solidity-wrappers.yml' + read_only_sol: + - 'contracts/src/v0.8/interfaces/**/*' + - 'contracts/src/v0.8/automation/v1_2/**/*' + - 'contracts/src/v0.8/automation/v1_3/**/*' + - 'contracts/src/v0.8/automation/v2_0/**/*' + + - name: Fail if read-only files have changed + if: ${{ steps.changed_files.outputs.read_only_sol == 'true' }} + shell: bash + run: | + echo "One or more read-only Solidity file(s) has changed." + for file in ${{ steps.changed_files.outputs.read_only_sol_files }}; do + echo "$file was changed" + done + exit 1 diff --git a/.github/workflows/solidity-wrappers.yml b/.github/workflows/solidity-wrappers.yml new file mode 100644 index 00000000000..56528611f36 --- /dev/null +++ b/.github/workflows/solidity-wrappers.yml @@ -0,0 +1,82 @@ +name: Solidity Wrappers +# This is its own workflow file rather than being merged into "solidity.yml" to avoid over complicating the conditionals +# used for job execution. The jobs in "solidity.yml" are configured around push events, whereas +# we only want to generate gethwrappers during pull requests. +on: + pull_request: + types: + - opened + - synchronize + - reopened + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + outputs: + changes: ${{ steps.ch.outputs.changes }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - name: Detect changes + id: ch + uses: ./.github/actions/detect-solidity-file-changes + + # On a pull request event, make updates to gethwrappers if there are changes. + update-wrappers: + needs: [changes] + if: needs.changes.outputs.changes == 'true' + name: Update Wrappers + permissions: + actions: read + id-token: write + contents: read + runs-on: ubuntu22.04-8cores-32GB + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Setup Go + uses: ./.github/actions/setup-go + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + with: + prod: "true" + + - name: Run native compile and generate wrappers + run: make wrappers-all + working-directory: ./contracts + + - name: Assume role capable of dispatching action + uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 + id: get-gh-token + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Commit any wrapper changes + uses: planetscale/ghcommit-action@21a8cda29f55e5cc2cdae0cdbdd08e38dd148c25 # v0.1.37 + with: + commit_message: "Update gethwrappers" + repo: ${{ github.repository }} + branch: ${{ github.head_ref }} + file_pattern: "core/gethwrappers/**/generated/*.go core/gethwrappers/**/generated-wrapper-dependency-versions-do-not-edit.txt" + env: + GITHUB_TOKEN: ${{ steps.get-gh-token.outputs.access-token }} + + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: solidity-update-wrappers + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Update Wrappers + continue-on-error: true diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index b2dc3d4153c..22ed53e72bc 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -13,33 +13,13 @@ jobs: name: Detect changes runs-on: ubuntu-latest outputs: - changes: ${{ steps.changes.outputs.src }} + changes: ${{ steps.ch.outputs.changes }} steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - with: - list-files: "csv" - filters: | - src: - - 'contracts/**/*' - - '.github/workflows/solidity.yml' - - '.github/workflows/solidity-foundry.yml' - read_only_sol: - - 'contracts/src/v0.8/interfaces/**/*' - - 'contracts/src/v0.8/automation/v1_2/**/*' - - 'contracts/src/v0.8/automation/v1_3/**/*' - - 'contracts/src/v0.8/automation/v2_0/**/*' - - - name: Fail if read-only files have changed - if: ${{ steps.changes.outputs.read_only_sol == 'true' }} - run: | - echo "One or more read-only Solidity file(s) has changed." - for file in ${{ steps.changes.outputs.read_only_sol_files }}; do - echo "$file was changed" - done - exit 1 + - name: Detect changes + id: ch + uses: ./.github/actions/detect-solidity-file-changes tag-check: needs: [changes] @@ -116,11 +96,6 @@ jobs: - name: Check if Go solidity wrappers are updated if: ${{ needs.changes.outputs.changes == 'true' }} run: git diff --minimal --color --exit-code | diff-so-fancy - - name: Comment on fix instructions - env: - GITHUB_TOKEN: ${{ github.token }} - if: ${{ failure() }} - run: gh pr comment -b 'Go solidity wrappers are out-of-date, regenerate them via the `make wrappers-all` command' - name: Collect Metrics id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 From 1e50baefe7be679f1da44612814d2fdef129abb1 Mon Sep 17 00:00:00 2001 From: Lee Yik Jiun Date: Thu, 2 May 2024 23:44:14 +0800 Subject: [PATCH 06/35] Add vrf coordinator v2.5 mock (#12873) * Add vrf coordinator v2.5 mock * Fix natspec complaining about inheritdoc references inexistent contract --- .../v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol | 268 +++++++++ .../vrf/test/VRFCoordinatorV2_5Mock.t.sol | 511 ++++++++++++++++++ .../vrf/testhelpers/VRFConsumerV2Plus.sol | 55 ++ 3 files changed, 834 insertions(+) create mode 100644 contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol create mode 100644 contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol create mode 100644 contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol diff --git a/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol b/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol new file mode 100644 index 00000000000..ac95c1e3177 --- /dev/null +++ b/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: MIT +// A mock for testing code that relies on VRFCoordinatorV2_5. +pragma solidity ^0.8.19; + +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; + +contract VRFCoordinatorV2_5Mock is SubscriptionAPI, IVRFCoordinatorV2Plus { + uint96 public immutable i_base_fee; + uint96 public immutable i_gas_price; + int256 public immutable i_wei_per_unit_link; + + error InvalidRequest(); + error InvalidRandomWords(); + error InvalidExtraArgsTag(); + error NotImplemented(); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + event ConfigSet(); + + uint64 internal s_currentSubId; + uint256 internal s_nextRequestId = 1; + uint256 internal s_nextPreSeed = 100; + + struct Request { + uint256 subId; + uint32 callbackGasLimit; + uint32 numWords; + bytes extraArgs; + } + mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ + + constructor(uint96 _baseFee, uint96 _gasPrice, int256 _weiPerUnitLink) SubscriptionAPI() { + i_base_fee = _baseFee; + i_gas_price = _gasPrice; + i_wei_per_unit_link = _weiPerUnitLink; + setConfig(); + } + + /** + * @notice Sets the configuration of the vrfv2 mock coordinator + */ + function setConfig() public onlyOwner { + s_config = Config({ + minimumRequestConfirmations: 0, + maxGasLimit: 0, + stalenessSeconds: 0, + gasAfterPaymentCalculation: 0, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: 0, + fulfillmentFlatFeeLinkDiscountPPM: 0, + nativePremiumPercentage: 0, + linkPremiumPercentage: 0 + }); + emit ConfigSet(); + } + + function consumerIsAdded(uint256 _subId, address _consumer) public view returns (bool) { + return s_consumers[_consumer][_subId].active; + } + + modifier onlyValidConsumer(uint256 _subId, address _consumer) { + if (!consumerIsAdded(_subId, _consumer)) { + revert InvalidConsumer(_subId, _consumer); + } + _; + } + + /** + * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied + * @notice consumer. + * + * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does + * @dev not account for all edge cases handled in the real VRF coordinator. When making requests + * @dev against the real coordinator a small amount of additional LINK is required. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + */ + function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { + fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); + } + + /** + * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + * @param _words user-provided random words + */ + function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { + uint256 startGas = gasleft(); + if (s_requests[_requestId].subId == 0) { + revert InvalidRequest(); + } + Request memory req = s_requests[_requestId]; + + if (_words.length == 0) { + _words = new uint256[](req.numWords); + for (uint256 i = 0; i < req.numWords; i++) { + _words[i] = uint256(keccak256(abi.encode(_requestId, i))); + } + } else if (_words.length != req.numWords) { + revert InvalidRandomWords(); + } + + VRFConsumerBaseV2Plus v; + bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); + s_config.reentrancyLock = true; + // solhint-disable-next-line avoid-low-level-calls, no-unused-vars + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); + s_config.reentrancyLock = false; + + bool nativePayment = uint8(req.extraArgs[req.extraArgs.length - 1]) == 1; + + uint256 rawPayment = i_base_fee + ((startGas - gasleft()) * i_gas_price); + if (!nativePayment) { + rawPayment = (1e18 * rawPayment) / uint256(i_wei_per_unit_link); + } + uint96 payment = uint96(rawPayment); + + _chargePayment(payment, nativePayment, req.subId); + + delete (s_requests[_requestId]); + emit RandomWordsFulfilled(_requestId, _requestId, req.subId, payment, nativePayment, success, false); + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + /** + * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. + * + * @param _subId the subscription to fund + * @param _amount the amount to fund + */ + function fundSubscription(uint256 _subId, uint256 _amount) public { + if (s_subscriptionConfigs[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + uint256 oldBalance = s_subscriptions[_subId].balance; + s_subscriptions[_subId].balance += uint96(_amount); + s_totalBalance += uint96(_amount); + emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata _req + ) external override nonReentrant onlyValidConsumer(_req.subId, msg.sender) returns (uint256) { + uint256 subId = _req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + + uint256 requestId = s_nextRequestId++; + uint256 preSeed = s_nextPreSeed++; + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(_req.extraArgs)); + s_requests[requestId] = Request({ + subId: _req.subId, + callbackGasLimit: _req.callbackGasLimit, + numWords: _req.numWords, + extraArgs: _req.extraArgs + }); + + emit RandomWordsRequested( + _req.keyHash, + requestId, + preSeed, + _req.subId, + _req.requestConfirmations, + _req.callbackGasLimit, + _req.numWords, + extraArgsBytes, + msg.sender + ); + return requestId; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer( + uint256 _subId, + address _consumer + ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { + if (!s_consumers[_consumer][_subId].active) { + revert InvalidConsumer(_subId, _consumer); + } + address[] memory consumers = s_subscriptionConfigs[_subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == _consumer) { + address last = consumers[lastConsumerIndex]; + s_subscriptionConfigs[_subId].consumers[i] = last; + s_subscriptionConfigs[_subId].consumers.pop(); + break; + } + } + s_consumers[_consumer][_subId].active = false; + emit SubscriptionConsumerRemoved(_subId, _consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { + (uint96 balance, uint96 nativeBalance) = _deleteSubscription(_subId); + + (bool success, ) = _to.call{value: uint256(nativeBalance)}(""); + if (!success) { + revert FailedToSendNative(); + } + emit SubscriptionCanceled(_subId, _to, balance, nativeBalance); + } + + function pendingRequestExists(uint256 /*subId*/) public pure override returns (bool) { + revert NotImplemented(); + } +} diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol new file mode 100644 index 00000000000..75c763c88cb --- /dev/null +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol @@ -0,0 +1,511 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFCoordinatorV2_5Mock} from "../mocks/VRFCoordinatorV2_5Mock.sol"; +import {VRFConsumerV2Plus} from "../testhelpers/VRFConsumerV2Plus.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; + +contract VRFCoordinatorV2_5MockTest is BaseTest { + MockLinkToken internal s_linkToken; + VRFCoordinatorV2_5Mock internal s_vrfCoordinatorV2_5Mock; + VRFConsumerV2Plus internal s_vrfConsumerV2Plus; + address internal s_subOwner = address(1234); + + bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; + uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; + uint32 internal constant DEFAULT_NUM_WORDS = 1; + + uint96 internal constant oneNative = 1 ether; + uint96 internal constant twoLink = 2 ether; + + event SubscriptionCreated(uint256 indexed subId, address owner); + event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); + event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(OWNER, 10_000 ether); + vm.deal(s_subOwner, 20 ether); + + // Deploy link token and link/eth feed. + s_linkToken = new MockLinkToken(); + + // Deploy coordinator and consumer. + s_vrfCoordinatorV2_5Mock = new VRFCoordinatorV2_5Mock(0.002 ether, 40 gwei, 0.004 ether); + address coordinatorAddr = address(s_vrfCoordinatorV2_5Mock); + s_vrfConsumerV2Plus = new VRFConsumerV2Plus(coordinatorAddr, address(s_linkToken)); + + s_vrfCoordinatorV2_5Mock.setConfig(); + } + + function test_CreateSubscription() public { + vm.startPrank(s_subOwner); + uint256 expectedSubId = uint256( + keccak256( + abi.encodePacked( + s_subOwner, + blockhash(block.number - 1), + address(s_vrfCoordinatorV2_5Mock), + s_vrfCoordinatorV2_5Mock.s_currentSubNonce() + ) + ) + ); + vm.expectEmit( + true, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit SubscriptionCreated(expectedSubId, s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + assertEq(subId, expectedSubId); + + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, 0); + assertEq(nativeBalance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 0); + vm.stopPrank(); + } + + function test_AddConsumer() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (uint96 balance, , uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2_5Mock + .getSubscription(subId); + assertEq(balance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add a consumer to a nonexistent subscription + function test_AddConsumerToInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add more than the consumer maximum + function test_AddMaxConsumers() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + // Add 100 consumers + for (uint64 i = 101; i <= 200; ++i) { + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); + } + // Adding 101th consumer should revert + vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can remove a consumer from a subscription + function test_RemoveConsumerFromSub() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + } + + // cannot remove a consumer from a nonexistent subscription + function test_RemoveConsumerFromInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.removeConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot remove a consumer after it is already removed + function test_RemoveConsumerAgain() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can fund a subscription + function test_FundSubscription() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, twoLink); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + (uint96 balance, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, twoLink); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), twoLink); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscription_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.stopPrank(); + } + + // can fund a subscription with native + function test_FundSubscriptionWithNative() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, oneNative); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + (, uint256 nativeBalance, , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(nativeBalance, oneNative); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), oneNative); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscriptionWithNative_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Link() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + uint256 totalBalance = s_vrfCoordinatorV2_5Mock.s_totalBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, twoLink, 0); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), totalBalance - twoLink); + + // sub owner balance did not increase as no actual token is involved + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Native() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + uint256 balance = address(s_subOwner).balance; + uint256 totalNativeBalance = s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, 0, oneNative); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), totalNativeBalance - oneNative); + + // check sub owner balance increased + assertEq(address(s_subOwner).balance, balance + oneNative); + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // fails to fulfill without being a valid consumer + function testFuzz_RequestRandomWords_RevertIfInvalidConsumer(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_subOwner))); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) + }); + s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + vm.stopPrank(); + } + + // fails to fulfill with insufficient funds + function testFuzz_RequestRandomWords_RevertIfInsufficientFunds(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + + vm.startPrank(consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + + vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Link_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 1432960000000000000, false, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Native_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 5731840000000000, true, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] + function testFuzz_RequestRandomWordsUserOverride(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + uint96 expectedPayment; + if (nativePayment) { + expectedPayment = 5011440000000000; + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + } else { + expectedPayment = 1252860000000000000; + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + } + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 2, + extraArgs, + address(s_subOwner) + ); + + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: 2, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectRevert(VRFCoordinatorV2_5Mock.InvalidRandomWords.selector); + uint256[] memory words1 = new uint256[](5); + words1[0] = 1; + words1[1] = 2; + words1[2] = 3; + words1[3] = 4; + words1[4] = 5; + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); + + vm.expectEmit(true, false, false, true); + uint256[] memory words2 = new uint256[](2); + words1[0] = 2533; + words1[1] = 1768; + emit RandomWordsFulfilled(reqId, 1, subId, expectedPayment, nativePayment, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); + + vm.stopPrank(); + } +} diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol b/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol new file mode 100644 index 00000000000..f0acade0bb6 --- /dev/null +++ b/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; + +contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { + uint256[] public s_randomWords; + uint256 public s_requestId; + IVRFCoordinatorV2Plus internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint256 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + COORDINATOR = IVRFCoordinatorV2Plus(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(req); + return s_requestId; + } +} From 03f0010ca213c34abe9f65a050feae7b9d8621c5 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 12:01:52 -0400 Subject: [PATCH 07/35] Add run attempt to run URL (#13063) --- tools/flakeytests/cmd/runner/main.go | 7 ++++++- tools/flakeytests/utils.go | 8 ++++---- tools/flakeytests/utils_test.go | 8 ++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go index 2a1c5633577..0e1be5e7d38 100644 --- a/tools/flakeytests/cmd/runner/main.go +++ b/tools/flakeytests/cmd/runner/main.go @@ -33,6 +33,11 @@ func main() { ghRunID := flag.String("gh_run_id", "", "run id of the gh workflow") flag.Parse() + runAttempt := os.Getenv("GITHUB_RUN_ATTEMPT") + if runAttempt == "" { + log.Fatalf("GITHUB_RUN_ATTEMPT is required") + } + if *grafanaHost == "" { log.Fatal("Error re-running flakey tests: `grafana_host` is required") } @@ -62,7 +67,7 @@ func main() { readers = append(readers, r) } - meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID) + meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID, runAttempt) rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *grafanaOrgID, *command, meta) r := flakeytests.NewRunner(readers, rep, numReruns) err := r.Run(ctx) diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go index d2326c47262..96d6a02ded5 100644 --- a/tools/flakeytests/utils.go +++ b/tools/flakeytests/utils.go @@ -30,7 +30,7 @@ func DigString(mp map[string]interface{}, path []string) (string, error) { return vs, nil } -func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, runID string) Context { +func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, runID string, runAttempt string) Context { d, err := io.ReadAll(e) if err != nil { log.Fatal("Error reading gh event into string") @@ -42,7 +42,7 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, r log.Fatalf("Error unmarshaling gh event at path") } - runURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID) + runURL := fmt.Sprintf("github.com/%s/actions/runs/%s/attempts/%s", repo, runID, runAttempt) basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: runURL} switch eventName { case "pull_request": @@ -70,10 +70,10 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, r } } -func GetGithubMetadata(repo string, eventName string, sha string, path string, runID string) Context { +func GetGithubMetadata(repo string, eventName string, sha string, path string, runID string, runAttempt string) Context { event, err := os.Open(path) if err != nil { log.Fatalf("Error reading gh event at path: %s", path) } - return getGithubMetadata(repo, eventName, sha, event, runID) + return getGithubMetadata(repo, eventName, sha, event, runID, runAttempt) } diff --git a/tools/flakeytests/utils_test.go b/tools/flakeytests/utils_test.go index 6ea912d11d4..d63ff041749 100644 --- a/tools/flakeytests/utils_test.go +++ b/tools/flakeytests/utils_test.go @@ -36,14 +36,14 @@ var prEventTemplate = ` ` func TestGetGithubMetadata(t *testing.T) { - repo, eventName, sha, event, runID := "chainlink", "merge_group", "a-sha", `{}`, "1234" - expectedRunURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID) - ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID) + repo, eventName, sha, event, runID, runAttempt := "chainlink", "merge_group", "a-sha", `{}`, "1234", "1" + expectedRunURL := fmt.Sprintf("github.com/%s/actions/runs/%s/attempts/%s", repo, runID, runAttempt) + ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID, runAttempt) assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: expectedRunURL}, ctx) anotherSha, eventName, url := "another-sha", "pull_request", "a-url" event = fmt.Sprintf(prEventTemplate, anotherSha, url) sha = "302eb05d592132309b264e316f443f1ceb81b6c3" - ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID) + ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID, runAttempt) assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url, RunURL: expectedRunURL}, ctx) } From 4c6f1341e0ceaad2603141f0a3f666bcf52fbc69 Mon Sep 17 00:00:00 2001 From: Tate Date: Thu, 2 May 2024 10:04:33 -0600 Subject: [PATCH 08/35] Fix CI-Scripts workflow to only run on pull_request (#13083) It was attempting to do this but also had push running which can mess up r --- .github/workflows/ci-scripts.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml index 814c354cfe6..536973fc998 100644 --- a/.github/workflows/ci-scripts.yml +++ b/.github/workflows/ci-scripts.yml @@ -1,12 +1,11 @@ name: CI Scripts on: - push: + merge_group: pull_request: jobs: lint-scripts: - if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 @@ -23,7 +22,6 @@ jobs: gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} test-scripts: - if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 From 1e23d736c53a17dbc3130ce52a80b6d168d06a41 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Thu, 2 May 2024 12:55:10 -0400 Subject: [PATCH 09/35] Remove node6 for CRIB chart values (#13003) * Remove node6 for CRIB chart values * Use future helm chart and correct path to values-profiles override * Add back .gitignore * Update unnecessary trigger on ci-scripts owrkflow * Revert "Update unnecessary trigger on ci-scripts owrkflow" This reverts commit 7f618a15a9b42ff8cb9e55754141dbfed89edac2. --------- Co-authored-by: Gheorghe Strimtu Co-authored-by: Tate --- .github/scripts/crib/pr-comment-crib-env.js | 1 - crib/.gitignore | 3 +++ crib/devspace.yaml | 17 +++-------------- 3 files changed, 6 insertions(+), 15 deletions(-) create mode 100644 crib/.gitignore diff --git a/.github/scripts/crib/pr-comment-crib-env.js b/.github/scripts/crib/pr-comment-crib-env.js index d569587baff..cc36a9deb7b 100755 --- a/.github/scripts/crib/pr-comment-crib-env.js +++ b/.github/scripts/crib/pr-comment-crib-env.js @@ -11,7 +11,6 @@ function generateSubdomains(subdomainPrefix, prNumber) { "node3", "node4", "node5", - "node6", "geth-1337-http", "geth-1337-ws", "geth-2337-http", diff --git a/crib/.gitignore b/crib/.gitignore new file mode 100644 index 00000000000..9edd651d4db --- /dev/null +++ b/crib/.gitignore @@ -0,0 +1,3 @@ +values-profiles/* +!values-profiles/values-dev.yaml.example +!values-profiles/README.md diff --git a/crib/devspace.yaml b/crib/devspace.yaml index 213fe4c24c7..f22e710f943 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -74,7 +74,7 @@ images: docker push $image hooks: - command: ./scripts/check_env_vars.sh - events: [ "before:deploy:app" ] + events: ["before:deploy:app"] - wait: running: true terminatedWithCode: 0 @@ -100,7 +100,7 @@ deployments: releaseName: "app" chart: name: ${CHAINLINK_CLUSTER_HELM_CHART_URI} - version: 0.5.0 + version: 0.6.0 # for simplicity, we define all the values here # they can be defined the same way in values.yml # devspace merges these "values" with the "values.yaml" before deploy @@ -217,8 +217,6 @@ deployments: image: ${runtime.images.app} - name: node-5 image: ${runtime.images.app} - - name: node-6 - image: ${runtime.images.app} # each CL node have a dedicated PostgreSQL 11.15 # use StatefulSet by setting: @@ -348,15 +346,6 @@ deployments: name: app-node-5 port: number: 6688 - - host: ${DEVSPACE_NAMESPACE}-node6.${DEVSPACE_INGRESS_BASE_DOMAIN} - http: - paths: - - path: / - backend: - service: - name: app-node-6 - port: - number: 6688 - host: ${DEVSPACE_NAMESPACE}-geth-1337-http.${DEVSPACE_INGRESS_BASE_DOMAIN} http: paths: @@ -432,4 +421,4 @@ profiles: path: deployments.app.helm.values.chainlink.global.overridesToml - op: add path: deployments.app.helm.valuesFiles - value: ["../charts/chainlink-cluster/values-profiles/values-dev.yaml"] + value: ["./values-profiles/values-dev.yaml"] From fbbadfb6a1ef746aff9a98178e6186e12f4a4f54 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Thu, 2 May 2024 12:37:28 -0700 Subject: [PATCH 10/35] fix: ci-core print-races to slack conditionals (#13086) --- .github/workflows/ci-core.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 1d7b58820b0..a3ea68380f9 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -170,7 +170,7 @@ jobs: env: OUTPUT_FILE: ./output.txt USE_TEE: false - CL_DATABASE_URL: ${{ env.DB_URL }} + CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... - name: Print Filtered Test Results if: ${{ failure() && matrix.type.cmd == 'go_core_tests' && needs.filter.outputs.changes == 'true' }} @@ -203,7 +203,7 @@ jobs: ./coverage.txt ./postgres_logs.txt - name: Notify Slack - if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.event.branch == 'develop') && needs.filter.outputs.changes == 'true' }} + if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.base_ref == 'develop') && needs.filter.outputs.changes == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} From 5633b51ba1516598d189e61908ea3c6e89da5f01 Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 2 May 2024 13:49:10 -0700 Subject: [PATCH 11/35] add coverage for registrar and registry (#12988) * add coverage for registry and registrar * address comments --- .../dev/test/AutomationRegistrar2_3.t.sol | 165 ++++++++++++++++++ .../dev/test/AutomationRegistry2_3.t.sol | 62 ++++++- .../v0.8/automation/dev/test/BaseTest.t.sol | 4 + 3 files changed, 229 insertions(+), 2 deletions(-) diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol index 76b808d1f05..2b55651dbe8 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol @@ -16,11 +16,97 @@ contract SetUp is BaseTest { function setUp() public override { super.setUp(); + vm.startPrank(OWNER); (registry, registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); vm.stopPrank(); // reset identity at the start of each test } } +contract CancelUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + // cancel the upkeep + vm.startPrank(OWNER); + bytes32 hash = keccak256(abi.encode(registrationParams)); + registrar.cancel(hash); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startUpkeepAdminBalance + amount, endUpkeepAdminBalance); + } +} + +contract ApproveUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startRegistryBalance = usdToken18.balanceOf(address(registry)); + + // approve the upkeep + vm.startPrank(OWNER); + registrar.approve(registrationParams); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endRegistryBalance = usdToken18.balanceOf(address(registry)); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startRegistryBalance + amount, endRegistryBalance); + } +} + contract RegisterUpkeep is SetUp { function testLink_autoApproveOff_happy() external { vm.startPrank(UPKEEP_ADMIN); @@ -75,6 +161,7 @@ contract RegisterUpkeep is SetUp { } function testLink_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -103,6 +190,7 @@ contract RegisterUpkeep is SetUp { } function testUSDToken_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -131,6 +219,7 @@ contract RegisterUpkeep is SetUp { } function testNative_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -241,4 +330,80 @@ contract RegisterUpkeep is SetUp { vm.expectRevert(AutomationRegistrar2_3.DuplicateEntry.selector); registrar.registerUpkeep(params); } + + function test_revertOnInsufficientPayment() external { + vm.startPrank(UPKEEP_ADMIN); + + // slightly less than the minimum amount + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))) - 1); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of insufficient payment + vm.expectRevert(AutomationRegistrar2_3.InsufficientPayment.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidAdminAddress() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: ZERO_ADDRESS, // zero address is invalid + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidAdminAddress.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidBillingToken() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = 1; + usdToken18_2.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(usdToken18_2)), // unsupported billing token + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidBillingToken.selector); + registrar.registerUpkeep(params); + } } diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 03138696436..6da98e16fe5 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -136,11 +136,69 @@ contract CheckUpkeep is SetUp { } } +contract WithdrawFunds is SetUp { + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.withdrawFunds(linkUpkeepID, STRANGER); + } + + function test_RevertsWhen_InvalidRecipient() external { + vm.expectRevert(Registry.InvalidRecipient.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); + } + + function test_RevertsWhen_UpkeepNotCanceled() external { + vm.expectRevert(Registry.UpkeepNotCanceled.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_Happy_Link() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); + uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); + + uint256 upkeepBalance = registry.getBalance(linkUpkeepID); + vm.expectEmit(); + emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); + } + + function test_Happy_USDToken() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(usdUpkeepID6); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); + uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); + + uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); + vm.expectEmit(); + emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); + + assertEq(registry.getBalance(usdUpkeepID6), 0); + assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); + } +} + contract AddFunds is SetUp { event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); // when msg.value is 0, it uses the ERC20 payment path - function testNative_msgValue0() external { + function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { vm.startPrank(OWNER); uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); @@ -150,7 +208,7 @@ contract AddFunds is SetUp { } // when msg.value is not 0, it uses the native payment path - function testNative_msgValueNot0() external { + function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored diff --git a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol index 5ae9a29fc15..bba195b83e6 100644 --- a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol @@ -43,6 +43,7 @@ contract BaseTest is Test { LinkToken internal linkToken; ERC20Mock6Decimals internal usdToken6; ERC20Mock internal usdToken18; + ERC20Mock internal usdToken18_2; WETH9 internal weth; MockV3Aggregator internal LINK_USD_FEED; MockV3Aggregator internal NATIVE_USD_FEED; @@ -76,6 +77,7 @@ contract BaseTest is Test { linkToken = new LinkToken(); linkToken.grantMintRole(OWNER); usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); weth = new WETH9(); @@ -128,6 +130,8 @@ contract BaseTest is Test { usdToken18.mint(FINANCE_ADMIN, 1000e18); usdToken18.mint(STRANGER, 1000e18); + usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); + usdToken6.mint(OWNER, 1000e6); usdToken6.mint(UPKEEP_ADMIN, 1000e6); usdToken6.mint(FINANCE_ADMIN, 1000e6); From 4e62b15d7ed98cb28ed08238f985b640a5892b37 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Thu, 2 May 2024 13:56:40 -0700 Subject: [PATCH 12/35] exclude build-image gha if just changing changelog (#13065) * exclude build-image gha if just changing changelog * fix --- .github/workflows/build-publish-pr.yml | 2 +- .github/workflows/build.yml | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-publish-pr.yml b/.github/workflows/build-publish-pr.yml index a70f1227cc9..0737b742dc8 100644 --- a/.github/workflows/build-publish-pr.yml +++ b/.github/workflows/build-publish-pr.yml @@ -11,7 +11,7 @@ on: jobs: build-publish-untrusted: - if: ${{ ! startsWith(github.ref_name, 'release/') }} + if: ${{ ! startsWith(github.ref_name, 'release/') || (! startsWith(github.head_ref, 'release/') && ! startsWith(github.ref_name, 'chore/'))}} runs-on: ubuntu-20.04 environment: sdlc permissions: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 193a7a5d671..45193f6dc35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,17 +6,39 @@ on: jobs: build-chainlink: runs-on: ubuntu-20.04 + if: ${{ ! startsWith(github.head_ref, 'release/') && ! startsWith(github.ref_name, 'chore/') }} steps: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: change + with: + predicate-quantifier: every + filters: | + changelog-only: + - 'CHANGELOG.md' + - '!common/**' + - '!contracts/**' + - '!core/**' + - '!crib/**' + - '!dashboard-lib/**' + - '!fuzz/**' + - '!integration-tests/**' + - '!internal/**' + - '!operator_ui/**' + - '!plugins/**' + - '!tools/**' + - name: Build chainlink image + if: ${{ steps.change.outputs.changelog-only == 'false' }} uses: ./.github/actions/build-sign-publish-chainlink with: dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} publish: false sign-images: false + - name: Collect Metrics if: always() id: collect-gha-metrics From 53f26b216583cbf3f84608920fd1840574672ab1 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 23:36:09 -0400 Subject: [PATCH 13/35] Skip multi-node.txtar test due to high flake rate (#13090) --- testdata/scripts/metrics/multi-node.txtar | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testdata/scripts/metrics/multi-node.txtar b/testdata/scripts/metrics/multi-node.txtar index c3928160443..0d43018c564 100644 --- a/testdata/scripts/metrics/multi-node.txtar +++ b/testdata/scripts/metrics/multi-node.txtar @@ -1,3 +1,4 @@ +skip 'High Flake Rate' # Check that metrics specified in the expected_metrics are present in /metrics response # start node exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' @@ -75,4 +76,4 @@ multi_node_states{chainId="68472",network="EVM",state="InvalidChainID"} multi_node_states{chainId="68472",network="EVM",state="OutOfSync"} multi_node_states{chainId="68472",network="EVM",state="Undialed"} multi_node_states{chainId="68472",network="EVM",state="Unreachable"} -multi_node_states{chainId="68472",network="EVM",state="Unusable"} \ No newline at end of file +multi_node_states{chainId="68472",network="EVM",state="Unusable"} From d79bdf16c5129cf7bc7cc5114f92eb07fd3fbf02 Mon Sep 17 00:00:00 2001 From: Austin Born Date: Fri, 3 May 2024 08:32:28 -0700 Subject: [PATCH 14/35] Add gethwrappers for Operator Forwarder contracts (#13084) * Add gethwrappers for operatorforwarder * Changeset * Update .changeset/ninety-students-return.md * make generate --- .changeset/ninety-students-return.md | 5 + core/gethwrappers/go_generate.go | 3 + .../authorized_forwarder.go | 983 ++++++++++ .../authorized_receiver.go | 363 ++++ .../link_token_receiver.go | 197 ++ .../generated/operator/operator.go | 1731 +++++++++++++++++ .../operator_factory/operator_factory.go | 632 ++++++ ...rapper-dependency-versions-do-not-edit.txt | 6 + .../operatorforwarder/go_generate.go | 10 + 9 files changed, 3930 insertions(+) create mode 100644 .changeset/ninety-students-return.md create mode 100644 core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go create mode 100644 core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go create mode 100644 core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go create mode 100644 core/gethwrappers/operatorforwarder/generated/operator/operator.go create mode 100644 core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go create mode 100644 core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt create mode 100644 core/gethwrappers/operatorforwarder/go_generate.go diff --git a/.changeset/ninety-students-return.md b/.changeset/ninety-students-return.md new file mode 100644 index 00000000000..d00737e7f24 --- /dev/null +++ b/.changeset/ninety-students-return.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated Add gethwrappers for operatorforwarder contracts diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index e31f7feb833..c5a55b18a05 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -155,6 +155,9 @@ package gethwrappers // Mercury //go:generate go generate ./llo-feeds +// Operator Forwarder +//go:generate go generate ./operatorforwarder + // Shared //go:generate go generate ./shared diff --git a/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go b/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go new file mode 100644 index 00000000000..03643c9154b --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go @@ -0,0 +1,983 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package authorized_forwarder + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "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/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var AuthorizedForwarderMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"OwnershipTransferRequestedWithMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"forward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tos\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"}],\"name\":\"multiForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"transferOwnershipWithMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620016993803806200169983398101604081905262000034916200029d565b82826001600160a01b038216620000925760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c557620000c58162000199565b50506001600160a01b0384166200012b5760405162461bcd60e51b815260206004820152602360248201527f4c696e6b20746f6b656e2063616e6e6f742062652061207a65726f206164647260448201526265737360e81b606482015260840162000089565b6001600160a01b038085166080528216156200018f57816001600160a01b0316836001600160a01b03167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e836040516200018691906200038e565b60405180910390a35b50505050620003c3565b336001600160a01b03821603620001f35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000089565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200025c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002945781810151838201526020016200027a565b50506000910152565b60008060008060808587031215620002b457600080fd5b620002bf8562000244565b9350620002cf6020860162000244565b9250620002df6040860162000244565b60608601519092506001600160401b0380821115620002fd57600080fd5b818701915087601f8301126200031257600080fd5b81518181111562000327576200032762000261565b604051601f8201601f19908116603f0116810190838211818310171562000352576200035262000261565b816040528281528a60208487010111156200036c57600080fd5b6200037f83602083016020880162000277565b979a9699509497505050505050565b6020815260008251806020840152620003af81604085016020870162000277565b601f01601f19169190910160400192915050565b6080516112ac620003ed6000396000818161016d0152818161037501526105d301526112ac6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063ee56997b1161005b578063ee56997b14610200578063f2fde38b14610213578063fa00763a1461022657600080fd5b806379ba5097146101c75780638da5cb5b146101cf578063b64fa9e6146101ed57600080fd5b80634d3e2323116100b25780634d3e23231461015557806357970e93146101685780636fadcf72146101b457600080fd5b8063033f49f7146100d9578063181f5a77146100ee5780632408afaa14610140575b600080fd5b6100ec6100e7366004610e72565b61026f565b005b61012a6040518060400160405280601981526020017f417574686f72697a6564466f7277617264657220312e312e300000000000000081525081565b6040516101379190610ef5565b60405180910390f35b610148610287565b6040516101379190610f61565b6100ec610163366004610e72565b6102f6565b61018f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610137565b6100ec6101c2366004610e72565b61036b565b6100ec61042d565b60005473ffffffffffffffffffffffffffffffffffffffff1661018f565b6100ec6101fb366004611007565b61052a565b6100ec61020e366004611073565b6106cb565b6100ec6102213660046110b5565b6109dc565b61025f6102343660046110b5565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460ff1690565b6040519015158152602001610137565b6102776109f0565b610282838383610a73565b505050565b606060038054806020026020016040519081016040528092919081815260200182805480156102ec57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102c1575b5050505050905090565b6102ff836109dc565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e848460405161035e9291906110d7565b60405180910390a3505050565b610373610c00565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e0000000060448201526064015b60405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff1633146104ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610424565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610532610c00565b82811461059b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f417272617973206d7573742068617665207468652073616d65206c656e6774686044820152606401610424565b60005b838110156106c45760008585838181106105ba576105ba611124565b90506020020160208101906105cf91906110b5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e000000006044820152606401610424565b6106b38185858581811061069c5761069c611124565b90506020028101906106ae9190611153565b610a73565b506106bd816111b8565b905061059e565b5050505050565b6106d3610c79565b610739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e646572730000006044820152606401610424565b806107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e64657200000000006044820152606401610424565b60035460005b8181101561083657600060026000600384815481106107c7576107c7611124565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082f816111b8565b90506107a6565b5060005b8281101561098e576002600085858481811061085857610858611124565b905060200201602081019061086d91906110b5565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156108fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e64657273006044820152606401610424565b60016002600086868581811061091657610916611124565b905060200201602081019061092b91906110b5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610987816111b8565b905061083a565b5061099b60038484610dac565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516109cf93929190611217565b60405180910390a1505050565b6109e46109f0565b6109ed81610cb7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610424565b565b73ffffffffffffffffffffffffffffffffffffffff83163b610af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e74726163740000000000006044820152606401610424565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610b1b92919061128f565b6000604051808303816000865af19150503d8060008114610b58576040519150601f19603f3d011682016040523d82523d6000602084013e610b5d565b606091505b5091509150816106c4578051600003610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f466f727761726465642063616c6c20726576657274656420776974686f75742060448201527f726561736f6e00000000000000000000000000000000000000000000000000006064820152608401610424565b805181602001fd5b3360009081526002602052604090205460ff16610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e64657200000000000000000000006044820152606401610424565b600033610c9b60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b3373ffffffffffffffffffffffffffffffffffffffff821603610d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610424565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e24579160200282015b82811115610e245781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610dcc565b50610e30929150610e34565b5090565b5b80821115610e305760008155600101610e35565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b919050565b600080600060408486031215610e8757600080fd5b610e9084610e49565b9250602084013567ffffffffffffffff80821115610ead57600080fd5b818601915086601f830112610ec157600080fd5b813581811115610ed057600080fd5b876020828501011115610ee257600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610faf57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f7d565b50909695505050505050565b60008083601f840112610fcd57600080fd5b50813567ffffffffffffffff811115610fe557600080fd5b6020830191508360208260051b850101111561100057600080fd5b9250929050565b6000806000806040858703121561101d57600080fd5b843567ffffffffffffffff8082111561103557600080fd5b61104188838901610fbb565b9096509450602087013591508082111561105a57600080fd5b5061106787828801610fbb565b95989497509550505050565b6000806020838503121561108657600080fd5b823567ffffffffffffffff81111561109d57600080fd5b6110a985828601610fbb565b90969095509350505050565b6000602082840312156110c757600080fd5b6110d082610e49565b9392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118857600080fd5b83018035915067ffffffffffffffff8211156111a357600080fd5b60200191503681900382131561100057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611210577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6040808252810183905260008460608301825b868110156112655773ffffffffffffffffffffffffffffffffffffffff61125084610e49565b1682526020928301929091019060010161122a565b50809250505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b818382376000910190815291905056fea164736f6c6343000813000a", +} + +var AuthorizedForwarderABI = AuthorizedForwarderMetaData.ABI + +var AuthorizedForwarderBin = AuthorizedForwarderMetaData.Bin + +func DeployAuthorizedForwarder(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, owner common.Address, recipient common.Address, message []byte) (common.Address, *types.Transaction, *AuthorizedForwarder, error) { + parsed, err := AuthorizedForwarderMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AuthorizedForwarderBin), backend, link, owner, recipient, message) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AuthorizedForwarder{address: address, abi: *parsed, AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil +} + +type AuthorizedForwarder struct { + address common.Address + abi abi.ABI + AuthorizedForwarderCaller + AuthorizedForwarderTransactor + AuthorizedForwarderFilterer +} + +type AuthorizedForwarderCaller struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderTransactor struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderFilterer struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderSession struct { + Contract *AuthorizedForwarder + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type AuthorizedForwarderCallerSession struct { + Contract *AuthorizedForwarderCaller + CallOpts bind.CallOpts +} + +type AuthorizedForwarderTransactorSession struct { + Contract *AuthorizedForwarderTransactor + TransactOpts bind.TransactOpts +} + +type AuthorizedForwarderRaw struct { + Contract *AuthorizedForwarder +} + +type AuthorizedForwarderCallerRaw struct { + Contract *AuthorizedForwarderCaller +} + +type AuthorizedForwarderTransactorRaw struct { + Contract *AuthorizedForwarderTransactor +} + +func NewAuthorizedForwarder(address common.Address, backend bind.ContractBackend) (*AuthorizedForwarder, error) { + abi, err := abi.JSON(strings.NewReader(AuthorizedForwarderABI)) + if err != nil { + return nil, err + } + contract, err := bindAuthorizedForwarder(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AuthorizedForwarder{address: address, abi: abi, AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil +} + +func NewAuthorizedForwarderCaller(address common.Address, caller bind.ContractCaller) (*AuthorizedForwarderCaller, error) { + contract, err := bindAuthorizedForwarder(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthorizedForwarderCaller{contract: contract}, nil +} + +func NewAuthorizedForwarderTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthorizedForwarderTransactor, error) { + contract, err := bindAuthorizedForwarder(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthorizedForwarderTransactor{contract: contract}, nil +} + +func NewAuthorizedForwarderFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthorizedForwarderFilterer, error) { + contract, err := bindAuthorizedForwarder(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthorizedForwarderFilterer{contract: contract}, nil +} + +func bindAuthorizedForwarder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AuthorizedForwarderMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedForwarder.Contract.AuthorizedForwarderCaller.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AuthorizedForwarderTransactor.contract.Transfer(opts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AuthorizedForwarderTransactor.contract.Transact(opts, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedForwarder.Contract.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.contract.Transfer(opts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.contract.Transact(opts, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedForwarder.Contract.GetAuthorizedSenders(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedForwarder.Contract.GetAuthorizedSenders(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedForwarder.Contract.IsAuthorizedSender(&_AuthorizedForwarder.CallOpts, sender) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedForwarder.Contract.IsAuthorizedSender(&_AuthorizedForwarder.CallOpts, sender) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) LinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "linkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) LinkToken() (common.Address, error) { + return _AuthorizedForwarder.Contract.LinkToken(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) LinkToken() (common.Address, error) { + return _AuthorizedForwarder.Contract.LinkToken(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) Owner() (common.Address, error) { + return _AuthorizedForwarder.Contract.Owner(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) Owner() (common.Address, error) { + return _AuthorizedForwarder.Contract.Owner(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TypeAndVersion() (string, error) { + return _AuthorizedForwarder.Contract.TypeAndVersion(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) TypeAndVersion() (string, error) { + return _AuthorizedForwarder.Contract.TypeAndVersion(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "acceptOwnership") +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) AcceptOwnership() (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AcceptOwnership(&_AuthorizedForwarder.TransactOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AcceptOwnership(&_AuthorizedForwarder.TransactOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) Forward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "forward", to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) Forward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.Forward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) Forward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.Forward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) MultiForward(opts *bind.TransactOpts, tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "multiForward", tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) MultiForward(tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.MultiForward(&_AuthorizedForwarder.TransactOpts, tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) MultiForward(tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.MultiForward(&_AuthorizedForwarder.TransactOpts, tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "ownerForward", to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.OwnerForward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.OwnerForward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.SetAuthorizedSenders(&_AuthorizedForwarder.TransactOpts, senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.SetAuthorizedSenders(&_AuthorizedForwarder.TransactOpts, senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "transferOwnership", to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnership(&_AuthorizedForwarder.TransactOpts, to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnership(&_AuthorizedForwarder.TransactOpts, to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) TransferOwnershipWithMessage(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "transferOwnershipWithMessage", to, message) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TransferOwnershipWithMessage(to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnershipWithMessage(&_AuthorizedForwarder.TransactOpts, to, message) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) TransferOwnershipWithMessage(to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnershipWithMessage(&_AuthorizedForwarder.TransactOpts, to, message) +} + +type AuthorizedForwarderAuthorizedSendersChangedIterator struct { + Event *AuthorizedForwarderAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedForwarderAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &AuthorizedForwarderAuthorizedSendersChangedIterator{contract: _AuthorizedForwarder.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderAuthorizedSendersChanged) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedForwarderAuthorizedSendersChanged, error) { + event := new(AuthorizedForwarderAuthorizedSendersChanged) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferRequestedIterator struct { + Event *AuthorizedForwarderOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferRequestedIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferRequested) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferRequested(log types.Log) (*AuthorizedForwarderOwnershipTransferRequested, error) { + event := new(AuthorizedForwarderOwnershipTransferRequested) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator struct { + Event *AuthorizedForwarderOwnershipTransferRequestedWithMessage + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferRequestedWithMessage struct { + From common.Address + To common.Address + Message []byte + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferRequestedWithMessage(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferRequestedWithMessage", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferRequestedWithMessage", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferRequestedWithMessage(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequestedWithMessage, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferRequestedWithMessage", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequestedWithMessage", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferRequestedWithMessage(log types.Log) (*AuthorizedForwarderOwnershipTransferRequestedWithMessage, error) { + event := new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequestedWithMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferredIterator struct { + Event *AuthorizedForwarderOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferredIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferred) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferred(log types.Log) (*AuthorizedForwarderOwnershipTransferred, error) { + event := new(AuthorizedForwarderOwnershipTransferred) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _AuthorizedForwarder.abi.Events["AuthorizedSendersChanged"].ID: + return _AuthorizedForwarder.ParseAuthorizedSendersChanged(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferRequested"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferRequested(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferRequestedWithMessage"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferRequestedWithMessage(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferred"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (AuthorizedForwarderAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (AuthorizedForwarderOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (AuthorizedForwarderOwnershipTransferRequestedWithMessage) Topic() common.Hash { + return common.HexToHash("0x4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e") +} + +func (AuthorizedForwarderOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_AuthorizedForwarder *AuthorizedForwarder) Address() common.Address { + return _AuthorizedForwarder.address +} + +type AuthorizedForwarderInterface interface { + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + LinkToken(opts *bind.CallOpts) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + Forward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + MultiForward(opts *bind.TransactOpts, tos []common.Address, datas [][]byte) (*types.Transaction, error) + + OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + TransferOwnershipWithMessage(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedForwarderAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedForwarderAuthorizedSendersChanged, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*AuthorizedForwarderOwnershipTransferRequested, error) + + FilterOwnershipTransferRequestedWithMessage(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator, error) + + WatchOwnershipTransferRequestedWithMessage(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequestedWithMessage, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequestedWithMessage(log types.Log) (*AuthorizedForwarderOwnershipTransferRequestedWithMessage, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*AuthorizedForwarderOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go b/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go new file mode 100644 index 00000000000..632d08b294b --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go @@ -0,0 +1,363 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package authorized_receiver + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "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/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var AuthorizedReceiverMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +var AuthorizedReceiverABI = AuthorizedReceiverMetaData.ABI + +type AuthorizedReceiver struct { + address common.Address + abi abi.ABI + AuthorizedReceiverCaller + AuthorizedReceiverTransactor + AuthorizedReceiverFilterer +} + +type AuthorizedReceiverCaller struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverTransactor struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverFilterer struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverSession struct { + Contract *AuthorizedReceiver + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type AuthorizedReceiverCallerSession struct { + Contract *AuthorizedReceiverCaller + CallOpts bind.CallOpts +} + +type AuthorizedReceiverTransactorSession struct { + Contract *AuthorizedReceiverTransactor + TransactOpts bind.TransactOpts +} + +type AuthorizedReceiverRaw struct { + Contract *AuthorizedReceiver +} + +type AuthorizedReceiverCallerRaw struct { + Contract *AuthorizedReceiverCaller +} + +type AuthorizedReceiverTransactorRaw struct { + Contract *AuthorizedReceiverTransactor +} + +func NewAuthorizedReceiver(address common.Address, backend bind.ContractBackend) (*AuthorizedReceiver, error) { + abi, err := abi.JSON(strings.NewReader(AuthorizedReceiverABI)) + if err != nil { + return nil, err + } + contract, err := bindAuthorizedReceiver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AuthorizedReceiver{address: address, abi: abi, AuthorizedReceiverCaller: AuthorizedReceiverCaller{contract: contract}, AuthorizedReceiverTransactor: AuthorizedReceiverTransactor{contract: contract}, AuthorizedReceiverFilterer: AuthorizedReceiverFilterer{contract: contract}}, nil +} + +func NewAuthorizedReceiverCaller(address common.Address, caller bind.ContractCaller) (*AuthorizedReceiverCaller, error) { + contract, err := bindAuthorizedReceiver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthorizedReceiverCaller{contract: contract}, nil +} + +func NewAuthorizedReceiverTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthorizedReceiverTransactor, error) { + contract, err := bindAuthorizedReceiver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthorizedReceiverTransactor{contract: contract}, nil +} + +func NewAuthorizedReceiverFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthorizedReceiverFilterer, error) { + contract, err := bindAuthorizedReceiver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthorizedReceiverFilterer{contract: contract}, nil +} + +func bindAuthorizedReceiver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AuthorizedReceiverMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedReceiver.Contract.AuthorizedReceiverCaller.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.AuthorizedReceiverTransactor.contract.Transfer(opts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.AuthorizedReceiverTransactor.contract.Transact(opts, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedReceiver.Contract.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.contract.Transfer(opts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.contract.Transact(opts, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _AuthorizedReceiver.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedReceiver.Contract.GetAuthorizedSenders(&_AuthorizedReceiver.CallOpts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedReceiver.Contract.GetAuthorizedSenders(&_AuthorizedReceiver.CallOpts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _AuthorizedReceiver.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedReceiver.Contract.IsAuthorizedSender(&_AuthorizedReceiver.CallOpts, sender) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedReceiver.Contract.IsAuthorizedSender(&_AuthorizedReceiver.CallOpts, sender) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.SetAuthorizedSenders(&_AuthorizedReceiver.TransactOpts, senders) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.SetAuthorizedSenders(&_AuthorizedReceiver.TransactOpts, senders) +} + +type AuthorizedReceiverAuthorizedSendersChangedIterator struct { + Event *AuthorizedReceiverAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedReceiverAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedReceiverAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedReceiverAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedReceiverAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _AuthorizedReceiver.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &AuthorizedReceiverAuthorizedSendersChangedIterator{contract: _AuthorizedReceiver.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedReceiverAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _AuthorizedReceiver.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedReceiverAuthorizedSendersChanged) + if err := _AuthorizedReceiver.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedReceiverAuthorizedSendersChanged, error) { + event := new(AuthorizedReceiverAuthorizedSendersChanged) + if err := _AuthorizedReceiver.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_AuthorizedReceiver *AuthorizedReceiver) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _AuthorizedReceiver.abi.Events["AuthorizedSendersChanged"].ID: + return _AuthorizedReceiver.ParseAuthorizedSendersChanged(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (AuthorizedReceiverAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (_AuthorizedReceiver *AuthorizedReceiver) Address() common.Address { + return _AuthorizedReceiver.address +} + +type AuthorizedReceiverInterface interface { + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedReceiverAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedReceiverAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedReceiverAuthorizedSendersChanged, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go b/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go new file mode 100644 index 00000000000..8a26281dbbb --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go @@ -0,0 +1,197 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package link_token_receiver + +import ( + "errors" + "math/big" + "strings" + + ethereum "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/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var LinkTokenReceiverMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"getChainlinkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +var LinkTokenReceiverABI = LinkTokenReceiverMetaData.ABI + +type LinkTokenReceiver struct { + address common.Address + abi abi.ABI + LinkTokenReceiverCaller + LinkTokenReceiverTransactor + LinkTokenReceiverFilterer +} + +type LinkTokenReceiverCaller struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverTransactor struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverFilterer struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverSession struct { + Contract *LinkTokenReceiver + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type LinkTokenReceiverCallerSession struct { + Contract *LinkTokenReceiverCaller + CallOpts bind.CallOpts +} + +type LinkTokenReceiverTransactorSession struct { + Contract *LinkTokenReceiverTransactor + TransactOpts bind.TransactOpts +} + +type LinkTokenReceiverRaw struct { + Contract *LinkTokenReceiver +} + +type LinkTokenReceiverCallerRaw struct { + Contract *LinkTokenReceiverCaller +} + +type LinkTokenReceiverTransactorRaw struct { + Contract *LinkTokenReceiverTransactor +} + +func NewLinkTokenReceiver(address common.Address, backend bind.ContractBackend) (*LinkTokenReceiver, error) { + abi, err := abi.JSON(strings.NewReader(LinkTokenReceiverABI)) + if err != nil { + return nil, err + } + contract, err := bindLinkTokenReceiver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LinkTokenReceiver{address: address, abi: abi, LinkTokenReceiverCaller: LinkTokenReceiverCaller{contract: contract}, LinkTokenReceiverTransactor: LinkTokenReceiverTransactor{contract: contract}, LinkTokenReceiverFilterer: LinkTokenReceiverFilterer{contract: contract}}, nil +} + +func NewLinkTokenReceiverCaller(address common.Address, caller bind.ContractCaller) (*LinkTokenReceiverCaller, error) { + contract, err := bindLinkTokenReceiver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LinkTokenReceiverCaller{contract: contract}, nil +} + +func NewLinkTokenReceiverTransactor(address common.Address, transactor bind.ContractTransactor) (*LinkTokenReceiverTransactor, error) { + contract, err := bindLinkTokenReceiver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LinkTokenReceiverTransactor{contract: contract}, nil +} + +func NewLinkTokenReceiverFilterer(address common.Address, filterer bind.ContractFilterer) (*LinkTokenReceiverFilterer, error) { + contract, err := bindLinkTokenReceiver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LinkTokenReceiverFilterer{contract: contract}, nil +} + +func bindLinkTokenReceiver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := LinkTokenReceiverMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LinkTokenReceiver.Contract.LinkTokenReceiverCaller.contract.Call(opts, result, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.LinkTokenReceiverTransactor.contract.Transfer(opts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.LinkTokenReceiverTransactor.contract.Transact(opts, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LinkTokenReceiver.Contract.contract.Call(opts, result, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.contract.Transfer(opts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.contract.Transact(opts, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCaller) GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _LinkTokenReceiver.contract.Call(opts, &out, "getChainlinkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_LinkTokenReceiver *LinkTokenReceiverSession) GetChainlinkToken() (common.Address, error) { + return _LinkTokenReceiver.Contract.GetChainlinkToken(&_LinkTokenReceiver.CallOpts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCallerSession) GetChainlinkToken() (common.Address, error) { + return _LinkTokenReceiver.Contract.GetChainlinkToken(&_LinkTokenReceiver.CallOpts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactor) OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.contract.Transact(opts, "onTokenTransfer", sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiverSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.OnTokenTransfer(&_LinkTokenReceiver.TransactOpts, sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.OnTokenTransfer(&_LinkTokenReceiver.TransactOpts, sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiver) Address() common.Address { + return _LinkTokenReceiver.address +} + +type LinkTokenReceiverInterface interface { + GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) + + OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/operator/operator.go b/core/gethwrappers/operatorforwarder/generated/operator/operator.go new file mode 100644 index 00000000000..71004cea91c --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/operator/operator.go @@ -0,0 +1,1731 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package operator + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "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/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var OperatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CancelOracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"callbackAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cancelExpiration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"OracleResponse\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"acceptedContract\",\"type\":\"address\"}],\"name\":\"OwnableContractAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"TargetsUpdatedAuthorizedSenders\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EXPIRYTIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"acceptAuthorizedReceivers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"ownable\",\"type\":\"address[]\"}],\"name\":\"acceptOwnableContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunc\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"cancelOracleRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunc\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"cancelOracleRequestByRequester\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable[]\",\"name\":\"receivers\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"distributeFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"fulfillOracleRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"fulfillOracleRequest2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainlinkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"operatorRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"oracleRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerTransferAndCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSendersOn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"ownable\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnableContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a060405260016006553480156200001657600080fd5b5060405162003aef38038062003aef8339810160408190526200003991620001ab565b808060006001600160a01b038216620000995760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0384811691909117909155811615620000cc57620000cc81620000e2565b505050506001600160a01b0316608052620001e3565b336001600160a01b038216036200013c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000090565b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b80516001600160a01b0381168114620001a657600080fd5b919050565b60008060408385031215620001bf57600080fd5b620001ca836200018e565b9150620001da602084016200018e565b90509250929050565b6080516138b16200023e600039600081816101ec0152818161075e015281816109f601528181610c520152818161189601528181611b0001528181611ba00152818161217e0152818161243101526129b901526138b16000f3fe6080604052600436106101965760003560e01c80636ae0bc76116100e1578063a4c0ed361161008a578063f2fde38b11610064578063f2fde38b146104aa578063f3fef3a3146104ca578063fa00763a146104ea578063fc4a03ed1461053057600080fd5b8063a4c0ed361461044a578063eb007d991461046a578063ee56997b1461048a57600080fd5b806379ba5097116100bb57806379ba5097146103ea5780638da5cb5b146103ff578063902fc3701461042a57600080fd5b80636ae0bc76146103975780636bd59ec0146103b75780636ee4d553146103ca57600080fd5b80633ec5bc1411610143578063501883011161011d578063501883011461033e57806352043783146103615780635ffa62881461037757600080fd5b80633ec5bc14146102ce57806340429946146102ee5780634ab0d1901461030e57600080fd5b8063181f5a7711610174578063181f5a77146102365780632408afaa1461028c5780633c6d41b9146102ae57600080fd5b806301994b991461019b578063033f49f7146101bd578063165d35e1146101dd575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004612e2c565b610550565b005b3480156101c957600080fd5b506101bb6101d8366004612ed2565b610753565b3480156101e957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561024257600080fd5b5061027f6040518060400160405280600e81526020017f4f70657261746f7220312e302e3000000000000000000000000000000000000081525081565b60405161022d9190612f4b565b34801561029857600080fd5b506102a161096f565b60405161022d9190612f9c565b3480156102ba57600080fd5b506101bb6102c936600461302b565b6109de565b3480156102da57600080fd5b506101bb6102e93660046130b8565b610ae6565b3480156102fa57600080fd5b506101bb61030936600461310f565b610c3a565b34801561031a57600080fd5b5061032e6103293660046131b2565b610d43565b604051901515815260200161022d565b34801561034a57600080fd5b50610353611039565b60405190815260200161022d565b34801561036d57600080fd5b5061035361012c81565b34801561038357600080fd5b506101bb61039236600461320c565b611048565b3480156103a357600080fd5b5061032e6103b2366004613278565b6110cc565b6101bb6103c536600461320c565b611448565b3480156103d657600080fd5b506101bb6103e53660046132fc565b611685565b3480156103f657600080fd5b506101bb611920565b34801561040b57600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff1661020c565b34801561043657600080fd5b5061032e610445366004613339565b611a21565b34801561045657600080fd5b506101bb6104653660046133b8565b611b88565b34801561047657600080fd5b506101bb6104853660046132fc565b611d16565b34801561049657600080fd5b506101bb6104a5366004612e2c565b611d70565b3480156104b657600080fd5b506101bb6104c53660046134a3565b61207e565b3480156104d657600080fd5b506101bb6104e53660046134c7565b612092565b3480156104f657600080fd5b5061032e6105053660046134a3565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b34801561053c57600080fd5b506101bb61054b36600461320c565b6121f7565b610558612353565b6105c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064015b60405180910390fd5b60005b8181101561074e576001600560008585858181106105e6576105e66134f3565b90506020020160208101906105fb91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055828282818110610660576106606134f3565b905060200201602081019061067591906134a3565b73ffffffffffffffffffffffffffffffffffffffff167f615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e8260405160405180910390a28282828181106106c9576106c96134f3565b90506020020160208101906106de91906134a3565b73ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508061074790613551565b90506105c6565b505050565b61075b6123a8565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b8373ffffffffffffffffffffffffffffffffffffffff163b600003610892576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e747261637400000000000060448201526064016105ba565b60008473ffffffffffffffffffffffffffffffffffffffff1684846040516108bb929190613589565b6000604051808303816000865af19150503d80600081146108f8576040519150601f19603f3d011682016040523d82523d6000602084013e6108fd565b606091505b5050905080610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f466f727761726465642063616c6c206661696c6564000000000000000000000060448201526064016105ba565b5050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156109d457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a9575b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610a8e8a8a8c8a8a8a61242b565b91509150877fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658b848c8e8c878c8c8c604051610ad2999897969594939291906135e2565b60405180910390a250505050505050505050565b610aee6123a8565b60005b82811015610c3457600060056000868685818110610b1157610b116134f3565b9050602002016020810190610b2691906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055838382818110610b8b57610b8b6134f3565b9050602002016020810190610ba091906134a3565b6040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152919091169063f2fde38b90602401600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b5050505080610c2d90613551565b9050610af1565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610cd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610cea8b8b8a8a8a8a61242b565b91509150887fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658c848d8f8c878c8c8c604051610d2e999897969594939291906135e2565b60405180910390a25050505050505050505050565b6000610d4d612709565b600087815260046020526040812054889160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260056020526040902054869060ff1615610e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b610e8f89898989896001612782565b60405189907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015610f27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008773ffffffffffffffffffffffffffffffffffffffff16878b87604051602401610f5d929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610fe6919061366d565b6000604051808303816000865af19150503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b50909b9a5050505050505050505050565b600061104361297a565b905090565b611050612353565b6110b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b6110c08484610550565b610c34848484846121f7565b60006110d6612709565b600088815260046020526040812054899160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003611177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040902054879060ff1615611209576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b8985856020811015611277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526573706f6e7365206d757374206265203e203332206279746573000000000060448201526064016105ba565b81358381146112e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f466972737420776f7264206d757374206265207265717565737449640000000060448201526064016105ba565b6112f18e8e8e8e8e6002612782565b6040518e907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008c73ffffffffffffffffffffffffffffffffffffffff168c8b8b6040516020016113b793929190613689565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526113ef9161366d565b6000604051808303816000865af19150503d806000811461142c576040519150601f19603f3d011682016040523d82523d6000602084013e611431565b606091505b509098505050505050505050979650505050505050565b821580159061145657508281145b6114bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c6964206172726179206c656e67746828732900000000000000000060448201526064016105ba565b3460005b8481101561161c5760008484838181106114dc576114dc6134f3565b90506020020135905080836114f191906136c5565b92506000878784818110611507576115076134f3565b905060200201602081019061151c91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611573576040519150601f19603f3d011682016040523d82523d6000602084013e611578565b606091505b5050905080611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105ba565b50508061161590613551565b90506114c0565b508015610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d756368204554482073656e7400000000000000000000000000000060448201526064016105ba565b6040805160208082018690527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16828401527fffffffff00000000000000000000000000000000000000000000000000000000851660548301526058808301859052835180840390910181526078909201909252805191012060009060008681526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146117a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b42821115611812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52657175657374206973206e6f7420657870697265640000000000000000000060448201526064016105ba565b6000858152600460205260408082208290555186917fa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e9391a2836006600082825461185c91906136c5565b90915550506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191891906136de565b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146119a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016105ba565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560038054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6000611a2b6123a8565b8380611a3561297a565b1015611ac3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517f4000aea000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634000aea090611b3b908990899089908990600401613700565b6020604051808303816000875af1158015611b5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7e91906136de565b9695505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b60208101518190611c388183612a43565b84602484015283604484015260003073ffffffffffffffffffffffffffffffffffffffff1684604051611c6b919061366d565b600060405180830381855af49150503d8060008114611ca6576040519150601f19603f3d011682016040523d82523d6000602084013e611cab565b606091505b5050905080611918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e61626c6520746f206372656174652072657175657374000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052610c349060540160405160208183030381529060405280519060200120848484611685565b611d78612353565b611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b80611e45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e646572000000000060448201526064016105ba565b60015460005b81811015611eda57600080600060018481548110611e6b57611e6b6134f3565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ed381613551565b9050611e4b565b5060005b8281101561203057600080858584818110611efb57611efb6134f3565b9050602002016020810190611f1091906134a3565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615611fa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e646572730060448201526064016105ba565b6001600080868685818110611fb857611fb86134f3565b9050602002016020810190611fcd91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561202981613551565b9050611ede565b5061203d60018484612d4c565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516120719392919061378c565b60405180910390a1505050565b6120866123a8565b61208f81612bbf565b50565b61209a6123a8565b80806120a461297a565b1015612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156121c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121eb91906136de565b61074e5761074e6137c6565b6121ff612353565b612265576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b7f1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727848484843360405161229c9594939291906137f5565b60405180910390a160005b83811015610968578484828181106122c1576122c16134f3565b90506020020160208101906122d691906134a3565b73ffffffffffffffffffffffffffffffffffffffff1663ee56997b84846040518363ffffffff1660e01b8152600401612310929190613845565b600060405180830381600087803b15801561232a57600080fd5b505af115801561233e573d6000803e3d6000fd5b505050508061234c90613551565b90506122a7565b3360009081526020819052604081205460ff168061104357503361238c60025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60025473ffffffffffffffffffffffffffffffffffffffff163314612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105ba565b565b600080857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b16602082015260348101869052605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206000818152600490935291205490935060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016156125ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d75737420757365206120756e6971756520494400000000000000000000000060448201526064016105ba565b6125fb61012c42613861565b6040805160208082018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16828401527fffffffff000000000000000000000000000000000000000000000000000000008a1660548301526058808301859052835180840390910181526078909201909252805191012090925060405180604001604052808260ff1916815260200161269a87612cb5565b60ff9081169091526000868152600460209081526040909120835193909101519091167f01000000000000000000000000000000000000000000000000000000000000000260089290921c9190911790556006546126f9908a90613861565b6006555050965096945050505050565b3360009081526020819052604090205460ff16612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e646572000000000000000000000060448201526064016105ba565b6040805160208082018890527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16828401527fffffffff00000000000000000000000000000000000000000000000000000000861660548301526058808301869052835180840390910181526078909201909252805191012060009060008881526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146128a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b6128af82612cb5565b60008881526004602052604090205460ff9182167f01000000000000000000000000000000000000000000000000000000000000009091049091161115612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f446174612076657273696f6e73206d757374206d61746368000000000000000060448201526064016105ba565b8560065461296091906136c5565b600655505050600093845250506004602052506040812055565b6000600160065461298b91906136c5565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190613874565b61104391906136c5565b612a4f6002602061388d565b612a5a906004613861565b81511015612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642072657175657374206c656e6774680000000000000000000060448201526064016105ba565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f3c6d41b9000000000000000000000000000000000000000000000000000000001480612b5557507fffffffff0000000000000000000000000000000000000000000000000000000082167f4042994600000000000000000000000000000000000000000000000000000000145b612bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d757374207573652077686974656c69737465642066756e6374696f6e73000060448201526064016105ba565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603612c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105ba565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b600060ff821115612d48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203860448201527f206269747300000000000000000000000000000000000000000000000000000060648201526084016105ba565b5090565b828054828255906000526020600020908101928215612dc4579160200282015b82811115612dc45781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190612d6c565b50612d489291505b80821115612d485760008155600101612dcc565b60008083601f840112612df257600080fd5b50813567ffffffffffffffff811115612e0a57600080fd5b6020830191508360208260051b8501011115612e2557600080fd5b9250929050565b60008060208385031215612e3f57600080fd5b823567ffffffffffffffff811115612e5657600080fd5b612e6285828601612de0565b90969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461208f57600080fd5b60008083601f840112612ea257600080fd5b50813567ffffffffffffffff811115612eba57600080fd5b602083019150836020828501011115612e2557600080fd5b600080600060408486031215612ee757600080fd5b8335612ef281612e6e565b9250602084013567ffffffffffffffff811115612f0e57600080fd5b612f1a86828701612e90565b9497909650939450505050565b60005b83811015612f42578181015183820152602001612f2a565b50506000910152565b6020815260008251806020840152612f6a816040850160208701612f27565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b81811015612fea57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fb8565b50909695505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461302657600080fd5b919050565b60008060008060008060008060e0898b03121561304757600080fd5b883561305281612e6e565b9750602089013596506040890135955061306e60608a01612ff6565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561309857600080fd5b6130a48b828c01612e90565b999c989b5096995094979396929594505050565b6000806000604084860312156130cd57600080fd5b833567ffffffffffffffff8111156130e457600080fd5b6130f086828701612de0565b909450925050602084013561310481612e6e565b809150509250925092565b60008060008060008060008060006101008a8c03121561312e57600080fd5b893561313981612e6e565b985060208a0135975060408a0135965060608a013561315781612e6e565b955061316560808b01612ff6565b945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff81111561318f57600080fd5b61319b8c828d01612e90565b915080935050809150509295985092959850929598565b60008060008060008060c087890312156131cb57600080fd5b863595506020870135945060408701356131e481612e6e565b93506131f260608801612ff6565b92506080870135915060a087013590509295509295509295565b6000806000806040858703121561322257600080fd5b843567ffffffffffffffff8082111561323a57600080fd5b61324688838901612de0565b9096509450602087013591508082111561325f57600080fd5b5061326c87828801612de0565b95989497509550505050565b600080600080600080600060c0888a03121561329357600080fd5b873596506020880135955060408801356132ac81612e6e565b94506132ba60608901612ff6565b93506080880135925060a088013567ffffffffffffffff8111156132dd57600080fd5b6132e98a828b01612e90565b989b979a50959850939692959293505050565b6000806000806080858703121561331257600080fd5b843593506020850135925061332960408601612ff6565b9396929550929360600135925050565b6000806000806060858703121561334f57600080fd5b843561335a81612e6e565b935060208501359250604085013567ffffffffffffffff81111561337d57600080fd5b61326c87828801612e90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156133cd57600080fd5b83356133d881612e6e565b925060208401359150604084013567ffffffffffffffff808211156133fc57600080fd5b818601915086601f83011261341057600080fd5b81358181111561342257613422613389565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561346857613468613389565b8160405282815289602084870101111561348157600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156134b557600080fd5b81356134c081612e6e565b9392505050565b600080604083850312156134da57600080fd5b82356134e581612e6e565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361358257613582613522565b5060010190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010073ffffffffffffffffffffffffffffffffffffffff808d1684528b60208501528a6040850152808a166060850152507fffffffff00000000000000000000000000000000000000000000000000000000881660808401528660a08401528560c08401528060e084015261365d8184018587613599565b9c9b505050505050505050505050565b6000825161367f818460208701612f27565b9190910192915050565b7fffffffff0000000000000000000000000000000000000000000000000000000084168152818360048301376000910160040190815292915050565b818103818111156136d8576136d8613522565b92915050565b6000602082840312156136f057600080fd5b815180151581146134c057600080fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611b7e606083018486613599565b8183526000602080850194508260005b8581101561378157813561375981612e6e565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613746565b509495945050505050565b6040815260006137a0604083018587613736565b905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b606081526000613809606083018789613736565b828103602084015261381c818688613736565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b602081526000613859602083018486613736565b949350505050565b808201808211156136d8576136d8613522565b60006020828403121561388657600080fd5b5051919050565b80820281158282048414176136d8576136d861352256fea164736f6c6343000813000a", +} + +var OperatorABI = OperatorMetaData.ABI + +var OperatorBin = OperatorMetaData.Bin + +func DeployOperator(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, owner common.Address) (common.Address, *types.Transaction, *Operator, error) { + parsed, err := OperatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OperatorBin), backend, link, owner) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Operator{address: address, abi: *parsed, OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil +} + +type Operator struct { + address common.Address + abi abi.ABI + OperatorCaller + OperatorTransactor + OperatorFilterer +} + +type OperatorCaller struct { + contract *bind.BoundContract +} + +type OperatorTransactor struct { + contract *bind.BoundContract +} + +type OperatorFilterer struct { + contract *bind.BoundContract +} + +type OperatorSession struct { + Contract *Operator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OperatorCallerSession struct { + Contract *OperatorCaller + CallOpts bind.CallOpts +} + +type OperatorTransactorSession struct { + Contract *OperatorTransactor + TransactOpts bind.TransactOpts +} + +type OperatorRaw struct { + Contract *Operator +} + +type OperatorCallerRaw struct { + Contract *OperatorCaller +} + +type OperatorTransactorRaw struct { + Contract *OperatorTransactor +} + +func NewOperator(address common.Address, backend bind.ContractBackend) (*Operator, error) { + abi, err := abi.JSON(strings.NewReader(OperatorABI)) + if err != nil { + return nil, err + } + contract, err := bindOperator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Operator{address: address, abi: abi, OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil +} + +func NewOperatorCaller(address common.Address, caller bind.ContractCaller) (*OperatorCaller, error) { + contract, err := bindOperator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OperatorCaller{contract: contract}, nil +} + +func NewOperatorTransactor(address common.Address, transactor bind.ContractTransactor) (*OperatorTransactor, error) { + contract, err := bindOperator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OperatorTransactor{contract: contract}, nil +} + +func NewOperatorFilterer(address common.Address, filterer bind.ContractFilterer) (*OperatorFilterer, error) { + contract, err := bindOperator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OperatorFilterer{contract: contract}, nil +} + +func bindOperator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OperatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Operator *OperatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Operator.Contract.OperatorCaller.contract.Call(opts, result, method, params...) +} + +func (_Operator *OperatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.Contract.OperatorTransactor.contract.Transfer(opts) +} + +func (_Operator *OperatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Operator.Contract.OperatorTransactor.contract.Transact(opts, method, params...) +} + +func (_Operator *OperatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Operator.Contract.contract.Call(opts, result, method, params...) +} + +func (_Operator *OperatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.Contract.contract.Transfer(opts) +} + +func (_Operator *OperatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Operator.Contract.contract.Transact(opts, method, params...) +} + +func (_Operator *OperatorCaller) EXPIRYTIME(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "EXPIRYTIME") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_Operator *OperatorSession) EXPIRYTIME() (*big.Int, error) { + return _Operator.Contract.EXPIRYTIME(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) EXPIRYTIME() (*big.Int, error) { + return _Operator.Contract.EXPIRYTIME(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) GetAuthorizedSenders() ([]common.Address, error) { + return _Operator.Contract.GetAuthorizedSenders(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _Operator.Contract.GetAuthorizedSenders(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "getChainlinkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) GetChainlinkToken() (common.Address, error) { + return _Operator.Contract.GetChainlinkToken(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) GetChainlinkToken() (common.Address, error) { + return _Operator.Contract.GetChainlinkToken(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_Operator *OperatorSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _Operator.Contract.IsAuthorizedSender(&_Operator.CallOpts, sender) +} + +func (_Operator *OperatorCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _Operator.Contract.IsAuthorizedSender(&_Operator.CallOpts, sender) +} + +func (_Operator *OperatorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) Owner() (common.Address, error) { + return _Operator.Contract.Owner(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) Owner() (common.Address, error) { + return _Operator.Contract.Owner(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_Operator *OperatorSession) TypeAndVersion() (string, error) { + return _Operator.Contract.TypeAndVersion(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) TypeAndVersion() (string, error) { + return _Operator.Contract.TypeAndVersion(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) Withdrawable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "withdrawable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_Operator *OperatorSession) Withdrawable() (*big.Int, error) { + return _Operator.Contract.Withdrawable(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) Withdrawable() (*big.Int, error) { + return _Operator.Contract.Withdrawable(&_Operator.CallOpts) +} + +func (_Operator *OperatorTransactor) AcceptAuthorizedReceivers(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptAuthorizedReceivers", targets, senders) +} + +func (_Operator *OperatorSession) AcceptAuthorizedReceivers(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptAuthorizedReceivers(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactorSession) AcceptAuthorizedReceivers(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptAuthorizedReceivers(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactor) AcceptOwnableContracts(opts *bind.TransactOpts, ownable []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptOwnableContracts", ownable) +} + +func (_Operator *OperatorSession) AcceptOwnableContracts(ownable []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnableContracts(&_Operator.TransactOpts, ownable) +} + +func (_Operator *OperatorTransactorSession) AcceptOwnableContracts(ownable []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnableContracts(&_Operator.TransactOpts, ownable) +} + +func (_Operator *OperatorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptOwnership") +} + +func (_Operator *OperatorSession) AcceptOwnership() (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnership(&_Operator.TransactOpts) +} + +func (_Operator *OperatorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnership(&_Operator.TransactOpts) +} + +func (_Operator *OperatorTransactor) CancelOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "cancelOracleRequest", requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorSession) CancelOracleRequest(requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactorSession) CancelOracleRequest(requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactor) CancelOracleRequestByRequester(opts *bind.TransactOpts, nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "cancelOracleRequestByRequester", nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorSession) CancelOracleRequestByRequester(nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequestByRequester(&_Operator.TransactOpts, nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactorSession) CancelOracleRequestByRequester(nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequestByRequester(&_Operator.TransactOpts, nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactor) DistributeFunds(opts *bind.TransactOpts, receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "distributeFunds", receivers, amounts) +} + +func (_Operator *OperatorSession) DistributeFunds(receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.Contract.DistributeFunds(&_Operator.TransactOpts, receivers, amounts) +} + +func (_Operator *OperatorTransactorSession) DistributeFunds(receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.Contract.DistributeFunds(&_Operator.TransactOpts, receivers, amounts) +} + +func (_Operator *OperatorTransactor) FulfillOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "fulfillOracleRequest", requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorSession) FulfillOracleRequest(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactorSession) FulfillOracleRequest(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactor) FulfillOracleRequest2(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "fulfillOracleRequest2", requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorSession) FulfillOracleRequest2(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest2(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactorSession) FulfillOracleRequest2(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest2(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactor) OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "onTokenTransfer", sender, amount, data) +} + +func (_Operator *OperatorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OnTokenTransfer(&_Operator.TransactOpts, sender, amount, data) +} + +func (_Operator *OperatorTransactorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OnTokenTransfer(&_Operator.TransactOpts, sender, amount, data) +} + +func (_Operator *OperatorTransactor) OperatorRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "operatorRequest", sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorSession) OperatorRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OperatorRequest(&_Operator.TransactOpts, sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactorSession) OperatorRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OperatorRequest(&_Operator.TransactOpts, sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactor) OracleRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "oracleRequest", sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorSession) OracleRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OracleRequest(&_Operator.TransactOpts, sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactorSession) OracleRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OracleRequest(&_Operator.TransactOpts, sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactor) OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "ownerForward", to, data) +} + +func (_Operator *OperatorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerForward(&_Operator.TransactOpts, to, data) +} + +func (_Operator *OperatorTransactorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerForward(&_Operator.TransactOpts, to, data) +} + +func (_Operator *OperatorTransactor) OwnerTransferAndCall(opts *bind.TransactOpts, to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "ownerTransferAndCall", to, value, data) +} + +func (_Operator *OperatorSession) OwnerTransferAndCall(to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerTransferAndCall(&_Operator.TransactOpts, to, value, data) +} + +func (_Operator *OperatorTransactorSession) OwnerTransferAndCall(to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerTransferAndCall(&_Operator.TransactOpts, to, value, data) +} + +func (_Operator *OperatorTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_Operator *OperatorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSenders(&_Operator.TransactOpts, senders) +} + +func (_Operator *OperatorTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSenders(&_Operator.TransactOpts, senders) +} + +func (_Operator *OperatorTransactor) SetAuthorizedSendersOn(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "setAuthorizedSendersOn", targets, senders) +} + +func (_Operator *OperatorSession) SetAuthorizedSendersOn(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSendersOn(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactorSession) SetAuthorizedSendersOn(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSendersOn(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactor) TransferOwnableContracts(opts *bind.TransactOpts, ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "transferOwnableContracts", ownable, newOwner) +} + +func (_Operator *OperatorSession) TransferOwnableContracts(ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnableContracts(&_Operator.TransactOpts, ownable, newOwner) +} + +func (_Operator *OperatorTransactorSession) TransferOwnableContracts(ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnableContracts(&_Operator.TransactOpts, ownable, newOwner) +} + +func (_Operator *OperatorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "transferOwnership", to) +} + +func (_Operator *OperatorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnership(&_Operator.TransactOpts, to) +} + +func (_Operator *OperatorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnership(&_Operator.TransactOpts, to) +} + +func (_Operator *OperatorTransactor) Withdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "withdraw", recipient, amount) +} + +func (_Operator *OperatorSession) Withdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.Contract.Withdraw(&_Operator.TransactOpts, recipient, amount) +} + +func (_Operator *OperatorTransactorSession) Withdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.Contract.Withdraw(&_Operator.TransactOpts, recipient, amount) +} + +type OperatorAuthorizedSendersChangedIterator struct { + Event *OperatorAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *OperatorAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*OperatorAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _Operator.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &OperatorAuthorizedSendersChangedIterator{contract: _Operator.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *OperatorAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _Operator.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorAuthorizedSendersChanged) + if err := _Operator.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseAuthorizedSendersChanged(log types.Log) (*OperatorAuthorizedSendersChanged, error) { + event := new(OperatorAuthorizedSendersChanged) + if err := _Operator.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorCancelOracleRequestIterator struct { + Event *OperatorCancelOracleRequest + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorCancelOracleRequestIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorCancelOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorCancelOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorCancelOracleRequestIterator) Error() error { + return it.fail +} + +func (it *OperatorCancelOracleRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorCancelOracleRequest struct { + RequestId [32]byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterCancelOracleRequest(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorCancelOracleRequestIterator, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "CancelOracleRequest", requestIdRule) + if err != nil { + return nil, err + } + return &OperatorCancelOracleRequestIterator{contract: _Operator.contract, event: "CancelOracleRequest", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchCancelOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorCancelOracleRequest, requestId [][32]byte) (event.Subscription, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "CancelOracleRequest", requestIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorCancelOracleRequest) + if err := _Operator.contract.UnpackLog(event, "CancelOracleRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseCancelOracleRequest(log types.Log) (*OperatorCancelOracleRequest, error) { + event := new(OperatorCancelOracleRequest) + if err := _Operator.contract.UnpackLog(event, "CancelOracleRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOracleRequestIterator struct { + Event *OperatorOracleRequest + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOracleRequestIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOracleRequestIterator) Error() error { + return it.fail +} + +func (it *OperatorOracleRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOracleRequest struct { + SpecId [32]byte + Requester common.Address + RequestId [32]byte + Payment *big.Int + CallbackAddr common.Address + CallbackFunctionId [4]byte + CancelExpiration *big.Int + DataVersion *big.Int + Data []byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOracleRequest(opts *bind.FilterOpts, specId [][32]byte) (*OperatorOracleRequestIterator, error) { + + var specIdRule []interface{} + for _, specIdItem := range specId { + specIdRule = append(specIdRule, specIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OracleRequest", specIdRule) + if err != nil { + return nil, err + } + return &OperatorOracleRequestIterator{contract: _Operator.contract, event: "OracleRequest", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorOracleRequest, specId [][32]byte) (event.Subscription, error) { + + var specIdRule []interface{} + for _, specIdItem := range specId { + specIdRule = append(specIdRule, specIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OracleRequest", specIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOracleRequest) + if err := _Operator.contract.UnpackLog(event, "OracleRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOracleRequest(log types.Log) (*OperatorOracleRequest, error) { + event := new(OperatorOracleRequest) + if err := _Operator.contract.UnpackLog(event, "OracleRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOracleResponseIterator struct { + Event *OperatorOracleResponse + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOracleResponseIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOracleResponse) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOracleResponse) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOracleResponseIterator) Error() error { + return it.fail +} + +func (it *OperatorOracleResponseIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOracleResponse struct { + RequestId [32]byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOracleResponse(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorOracleResponseIterator, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OracleResponse", requestIdRule) + if err != nil { + return nil, err + } + return &OperatorOracleResponseIterator{contract: _Operator.contract, event: "OracleResponse", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOracleResponse(opts *bind.WatchOpts, sink chan<- *OperatorOracleResponse, requestId [][32]byte) (event.Subscription, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OracleResponse", requestIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOracleResponse) + if err := _Operator.contract.UnpackLog(event, "OracleResponse", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOracleResponse(log types.Log) (*OperatorOracleResponse, error) { + event := new(OperatorOracleResponse) + if err := _Operator.contract.UnpackLog(event, "OracleResponse", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnableContractAcceptedIterator struct { + Event *OperatorOwnableContractAccepted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnableContractAcceptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnableContractAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnableContractAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnableContractAcceptedIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnableContractAcceptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnableContractAccepted struct { + AcceptedContract common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnableContractAccepted(opts *bind.FilterOpts, acceptedContract []common.Address) (*OperatorOwnableContractAcceptedIterator, error) { + + var acceptedContractRule []interface{} + for _, acceptedContractItem := range acceptedContract { + acceptedContractRule = append(acceptedContractRule, acceptedContractItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnableContractAccepted", acceptedContractRule) + if err != nil { + return nil, err + } + return &OperatorOwnableContractAcceptedIterator{contract: _Operator.contract, event: "OwnableContractAccepted", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnableContractAccepted(opts *bind.WatchOpts, sink chan<- *OperatorOwnableContractAccepted, acceptedContract []common.Address) (event.Subscription, error) { + + var acceptedContractRule []interface{} + for _, acceptedContractItem := range acceptedContract { + acceptedContractRule = append(acceptedContractRule, acceptedContractItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnableContractAccepted", acceptedContractRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnableContractAccepted) + if err := _Operator.contract.UnpackLog(event, "OwnableContractAccepted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnableContractAccepted(log types.Log) (*OperatorOwnableContractAccepted, error) { + event := new(OperatorOwnableContractAccepted) + if err := _Operator.contract.UnpackLog(event, "OwnableContractAccepted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnershipTransferRequestedIterator struct { + Event *OperatorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OperatorOwnershipTransferRequestedIterator{contract: _Operator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnershipTransferRequested) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnershipTransferRequested(log types.Log) (*OperatorOwnershipTransferRequested, error) { + event := new(OperatorOwnershipTransferRequested) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnershipTransferredIterator struct { + Event *OperatorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OperatorOwnershipTransferredIterator{contract: _Operator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnershipTransferred) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnershipTransferred(log types.Log) (*OperatorOwnershipTransferred, error) { + event := new(OperatorOwnershipTransferred) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorTargetsUpdatedAuthorizedSendersIterator struct { + Event *OperatorTargetsUpdatedAuthorizedSenders + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorTargetsUpdatedAuthorizedSenders) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorTargetsUpdatedAuthorizedSenders) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Error() error { + return it.fail +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorTargetsUpdatedAuthorizedSenders struct { + Targets []common.Address + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterTargetsUpdatedAuthorizedSenders(opts *bind.FilterOpts) (*OperatorTargetsUpdatedAuthorizedSendersIterator, error) { + + logs, sub, err := _Operator.contract.FilterLogs(opts, "TargetsUpdatedAuthorizedSenders") + if err != nil { + return nil, err + } + return &OperatorTargetsUpdatedAuthorizedSendersIterator{contract: _Operator.contract, event: "TargetsUpdatedAuthorizedSenders", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchTargetsUpdatedAuthorizedSenders(opts *bind.WatchOpts, sink chan<- *OperatorTargetsUpdatedAuthorizedSenders) (event.Subscription, error) { + + logs, sub, err := _Operator.contract.WatchLogs(opts, "TargetsUpdatedAuthorizedSenders") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorTargetsUpdatedAuthorizedSenders) + if err := _Operator.contract.UnpackLog(event, "TargetsUpdatedAuthorizedSenders", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseTargetsUpdatedAuthorizedSenders(log types.Log) (*OperatorTargetsUpdatedAuthorizedSenders, error) { + event := new(OperatorTargetsUpdatedAuthorizedSenders) + if err := _Operator.contract.UnpackLog(event, "TargetsUpdatedAuthorizedSenders", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_Operator *Operator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _Operator.abi.Events["AuthorizedSendersChanged"].ID: + return _Operator.ParseAuthorizedSendersChanged(log) + case _Operator.abi.Events["CancelOracleRequest"].ID: + return _Operator.ParseCancelOracleRequest(log) + case _Operator.abi.Events["OracleRequest"].ID: + return _Operator.ParseOracleRequest(log) + case _Operator.abi.Events["OracleResponse"].ID: + return _Operator.ParseOracleResponse(log) + case _Operator.abi.Events["OwnableContractAccepted"].ID: + return _Operator.ParseOwnableContractAccepted(log) + case _Operator.abi.Events["OwnershipTransferRequested"].ID: + return _Operator.ParseOwnershipTransferRequested(log) + case _Operator.abi.Events["OwnershipTransferred"].ID: + return _Operator.ParseOwnershipTransferred(log) + case _Operator.abi.Events["TargetsUpdatedAuthorizedSenders"].ID: + return _Operator.ParseTargetsUpdatedAuthorizedSenders(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OperatorAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (OperatorCancelOracleRequest) Topic() common.Hash { + return common.HexToHash("0xa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e93") +} + +func (OperatorOracleRequest) Topic() common.Hash { + return common.HexToHash("0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65") +} + +func (OperatorOracleResponse) Topic() common.Hash { + return common.HexToHash("0x9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a64") +} + +func (OperatorOwnableContractAccepted) Topic() common.Hash { + return common.HexToHash("0x615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e82") +} + +func (OperatorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OperatorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (OperatorTargetsUpdatedAuthorizedSenders) Topic() common.Hash { + return common.HexToHash("0x1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727") +} + +func (_Operator *Operator) Address() common.Address { + return _Operator.address +} + +type OperatorInterface interface { + EXPIRYTIME(opts *bind.CallOpts) (*big.Int, error) + + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + Withdrawable(opts *bind.CallOpts) (*big.Int, error) + + AcceptAuthorizedReceivers(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) + + AcceptOwnableContracts(opts *bind.TransactOpts, ownable []common.Address) (*types.Transaction, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + CancelOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) + + CancelOracleRequestByRequester(opts *bind.TransactOpts, nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) + + DistributeFunds(opts *bind.TransactOpts, receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) + + FulfillOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) + + FulfillOracleRequest2(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + OperatorRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) + + OracleRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) + + OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + OwnerTransferAndCall(opts *bind.TransactOpts, to common.Address, value *big.Int, data []byte) (*types.Transaction, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + SetAuthorizedSendersOn(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) + + TransferOwnableContracts(opts *bind.TransactOpts, ownable []common.Address, newOwner common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Withdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*OperatorAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *OperatorAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*OperatorAuthorizedSendersChanged, error) + + FilterCancelOracleRequest(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorCancelOracleRequestIterator, error) + + WatchCancelOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorCancelOracleRequest, requestId [][32]byte) (event.Subscription, error) + + ParseCancelOracleRequest(log types.Log) (*OperatorCancelOracleRequest, error) + + FilterOracleRequest(opts *bind.FilterOpts, specId [][32]byte) (*OperatorOracleRequestIterator, error) + + WatchOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorOracleRequest, specId [][32]byte) (event.Subscription, error) + + ParseOracleRequest(log types.Log) (*OperatorOracleRequest, error) + + FilterOracleResponse(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorOracleResponseIterator, error) + + WatchOracleResponse(opts *bind.WatchOpts, sink chan<- *OperatorOracleResponse, requestId [][32]byte) (event.Subscription, error) + + ParseOracleResponse(log types.Log) (*OperatorOracleResponse, error) + + FilterOwnableContractAccepted(opts *bind.FilterOpts, acceptedContract []common.Address) (*OperatorOwnableContractAcceptedIterator, error) + + WatchOwnableContractAccepted(opts *bind.WatchOpts, sink chan<- *OperatorOwnableContractAccepted, acceptedContract []common.Address) (event.Subscription, error) + + ParseOwnableContractAccepted(log types.Log) (*OperatorOwnableContractAccepted, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OperatorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OperatorOwnershipTransferred, error) + + FilterTargetsUpdatedAuthorizedSenders(opts *bind.FilterOpts) (*OperatorTargetsUpdatedAuthorizedSendersIterator, error) + + WatchTargetsUpdatedAuthorizedSenders(opts *bind.WatchOpts, sink chan<- *OperatorTargetsUpdatedAuthorizedSenders) (event.Subscription, error) + + ParseTargetsUpdatedAuthorizedSenders(log types.Log) (*OperatorTargetsUpdatedAuthorizedSenders, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go b/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go new file mode 100644 index 00000000000..4fc5e7448c5 --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go @@ -0,0 +1,632 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package operator_factory + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "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/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var OperatorFactoryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"linkAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AuthorizedForwarderCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"OperatorCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"created\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"deployNewForwarderAndTransferOwnership\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewOperatorAndForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a060405234801561001057600080fd5b50604051615b16380380615b1683398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051615a686100ae6000396000818161014f015281816101e6015281816102e3015281816103da015281816104be01526105a50152615a686000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c806357970e93116200006257806357970e931462000149578063d42efd831462000171578063d689d09514620001be578063f4adb6e114620001d557600080fd5b8063181f5a77146200008c57806332f01eae14620000e15780633babafdb1462000119575b600080fd5b620000c96040518060400160405280601581526020017f4f70657261746f72466163746f727920312e302e30000000000000000000000081525081565b604051620000d8919062000717565b60405180910390f35b620000eb620001df565b6040805173ffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201620000d8565b62000123620003c6565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620001237f000000000000000000000000000000000000000000000000000000000000000081565b620001ad620001823660046200075d565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b6040519015158152602001620000d8565b62000123620001cf3660046200077b565b620004b9565b62000123620005a0565b60008060007f000000000000000000000000000000000000000000000000000000000000000033604051620002149062000695565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000255573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917fd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab91a4604080516000808252602082019092527f000000000000000000000000000000000000000000000000000000000000000090309084906040516200031590620006a3565b62000324949392919062000805565b604051809103906000f08015801562000341573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033923092917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a490939092509050565b6040805160008082526020820190925281907f000000000000000000000000000000000000000000000000000000000000000090339083906040516200040c90620006a3565b6200041b949392919062000805565b604051809103906000f08015801562000438573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a4919050565b6000807f000000000000000000000000000000000000000000000000000000000000000033868686604051620004ef90620006a3565b620004ff95949392919062000852565b604051809103906000f0801580156200051c573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a4949350505050565b6000807f000000000000000000000000000000000000000000000000000000000000000033604051620005d39062000695565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000614573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917fd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab91a4919050565b613aef80620008d483390190565b61169980620043c383390190565b6000815180845260005b81811015620006d957602081850181015186830182015201620006bb565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006200072c6020830184620006b1565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200075857600080fd5b919050565b6000602082840312156200077057600080fd5b6200072c8262000733565b6000806000604084860312156200079157600080fd5b6200079c8462000733565b9250602084013567ffffffffffffffff80821115620007ba57600080fd5b818601915086601f830112620007cf57600080fd5b813581811115620007df57600080fd5b876020828501011115620007f257600080fd5b6020830194508093505050509250925092565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015280851660408401525060806060830152620008486080830184620006b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352808716602084015280861660408401525060806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501168301019050969550505050505056fe60a060405260016006553480156200001657600080fd5b5060405162003aef38038062003aef8339810160408190526200003991620001ab565b808060006001600160a01b038216620000995760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0384811691909117909155811615620000cc57620000cc81620000e2565b505050506001600160a01b0316608052620001e3565b336001600160a01b038216036200013c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000090565b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b80516001600160a01b0381168114620001a657600080fd5b919050565b60008060408385031215620001bf57600080fd5b620001ca836200018e565b9150620001da602084016200018e565b90509250929050565b6080516138b16200023e600039600081816101ec0152818161075e015281816109f601528181610c520152818161189601528181611b0001528181611ba00152818161217e0152818161243101526129b901526138b16000f3fe6080604052600436106101965760003560e01c80636ae0bc76116100e1578063a4c0ed361161008a578063f2fde38b11610064578063f2fde38b146104aa578063f3fef3a3146104ca578063fa00763a146104ea578063fc4a03ed1461053057600080fd5b8063a4c0ed361461044a578063eb007d991461046a578063ee56997b1461048a57600080fd5b806379ba5097116100bb57806379ba5097146103ea5780638da5cb5b146103ff578063902fc3701461042a57600080fd5b80636ae0bc76146103975780636bd59ec0146103b75780636ee4d553146103ca57600080fd5b80633ec5bc1411610143578063501883011161011d578063501883011461033e57806352043783146103615780635ffa62881461037757600080fd5b80633ec5bc14146102ce57806340429946146102ee5780634ab0d1901461030e57600080fd5b8063181f5a7711610174578063181f5a77146102365780632408afaa1461028c5780633c6d41b9146102ae57600080fd5b806301994b991461019b578063033f49f7146101bd578063165d35e1146101dd575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004612e2c565b610550565b005b3480156101c957600080fd5b506101bb6101d8366004612ed2565b610753565b3480156101e957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561024257600080fd5b5061027f6040518060400160405280600e81526020017f4f70657261746f7220312e302e3000000000000000000000000000000000000081525081565b60405161022d9190612f4b565b34801561029857600080fd5b506102a161096f565b60405161022d9190612f9c565b3480156102ba57600080fd5b506101bb6102c936600461302b565b6109de565b3480156102da57600080fd5b506101bb6102e93660046130b8565b610ae6565b3480156102fa57600080fd5b506101bb61030936600461310f565b610c3a565b34801561031a57600080fd5b5061032e6103293660046131b2565b610d43565b604051901515815260200161022d565b34801561034a57600080fd5b50610353611039565b60405190815260200161022d565b34801561036d57600080fd5b5061035361012c81565b34801561038357600080fd5b506101bb61039236600461320c565b611048565b3480156103a357600080fd5b5061032e6103b2366004613278565b6110cc565b6101bb6103c536600461320c565b611448565b3480156103d657600080fd5b506101bb6103e53660046132fc565b611685565b3480156103f657600080fd5b506101bb611920565b34801561040b57600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff1661020c565b34801561043657600080fd5b5061032e610445366004613339565b611a21565b34801561045657600080fd5b506101bb6104653660046133b8565b611b88565b34801561047657600080fd5b506101bb6104853660046132fc565b611d16565b34801561049657600080fd5b506101bb6104a5366004612e2c565b611d70565b3480156104b657600080fd5b506101bb6104c53660046134a3565b61207e565b3480156104d657600080fd5b506101bb6104e53660046134c7565b612092565b3480156104f657600080fd5b5061032e6105053660046134a3565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b34801561053c57600080fd5b506101bb61054b36600461320c565b6121f7565b610558612353565b6105c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064015b60405180910390fd5b60005b8181101561074e576001600560008585858181106105e6576105e66134f3565b90506020020160208101906105fb91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055828282818110610660576106606134f3565b905060200201602081019061067591906134a3565b73ffffffffffffffffffffffffffffffffffffffff167f615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e8260405160405180910390a28282828181106106c9576106c96134f3565b90506020020160208101906106de91906134a3565b73ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508061074790613551565b90506105c6565b505050565b61075b6123a8565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b8373ffffffffffffffffffffffffffffffffffffffff163b600003610892576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e747261637400000000000060448201526064016105ba565b60008473ffffffffffffffffffffffffffffffffffffffff1684846040516108bb929190613589565b6000604051808303816000865af19150503d80600081146108f8576040519150601f19603f3d011682016040523d82523d6000602084013e6108fd565b606091505b5050905080610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f466f727761726465642063616c6c206661696c6564000000000000000000000060448201526064016105ba565b5050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156109d457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a9575b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610a8e8a8a8c8a8a8a61242b565b91509150877fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658b848c8e8c878c8c8c604051610ad2999897969594939291906135e2565b60405180910390a250505050505050505050565b610aee6123a8565b60005b82811015610c3457600060056000868685818110610b1157610b116134f3565b9050602002016020810190610b2691906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055838382818110610b8b57610b8b6134f3565b9050602002016020810190610ba091906134a3565b6040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152919091169063f2fde38b90602401600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b5050505080610c2d90613551565b9050610af1565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610cd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610cea8b8b8a8a8a8a61242b565b91509150887fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658c848d8f8c878c8c8c604051610d2e999897969594939291906135e2565b60405180910390a25050505050505050505050565b6000610d4d612709565b600087815260046020526040812054889160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260056020526040902054869060ff1615610e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b610e8f89898989896001612782565b60405189907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015610f27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008773ffffffffffffffffffffffffffffffffffffffff16878b87604051602401610f5d929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610fe6919061366d565b6000604051808303816000865af19150503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b50909b9a5050505050505050505050565b600061104361297a565b905090565b611050612353565b6110b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b6110c08484610550565b610c34848484846121f7565b60006110d6612709565b600088815260046020526040812054899160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003611177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040902054879060ff1615611209576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b8985856020811015611277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526573706f6e7365206d757374206265203e203332206279746573000000000060448201526064016105ba565b81358381146112e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f466972737420776f7264206d757374206265207265717565737449640000000060448201526064016105ba565b6112f18e8e8e8e8e6002612782565b6040518e907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008c73ffffffffffffffffffffffffffffffffffffffff168c8b8b6040516020016113b793929190613689565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526113ef9161366d565b6000604051808303816000865af19150503d806000811461142c576040519150601f19603f3d011682016040523d82523d6000602084013e611431565b606091505b509098505050505050505050979650505050505050565b821580159061145657508281145b6114bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c6964206172726179206c656e67746828732900000000000000000060448201526064016105ba565b3460005b8481101561161c5760008484838181106114dc576114dc6134f3565b90506020020135905080836114f191906136c5565b92506000878784818110611507576115076134f3565b905060200201602081019061151c91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611573576040519150601f19603f3d011682016040523d82523d6000602084013e611578565b606091505b5050905080611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105ba565b50508061161590613551565b90506114c0565b508015610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d756368204554482073656e7400000000000000000000000000000060448201526064016105ba565b6040805160208082018690527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16828401527fffffffff00000000000000000000000000000000000000000000000000000000851660548301526058808301859052835180840390910181526078909201909252805191012060009060008681526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146117a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b42821115611812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52657175657374206973206e6f7420657870697265640000000000000000000060448201526064016105ba565b6000858152600460205260408082208290555186917fa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e9391a2836006600082825461185c91906136c5565b90915550506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191891906136de565b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146119a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016105ba565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560038054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6000611a2b6123a8565b8380611a3561297a565b1015611ac3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517f4000aea000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634000aea090611b3b908990899089908990600401613700565b6020604051808303816000875af1158015611b5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7e91906136de565b9695505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b60208101518190611c388183612a43565b84602484015283604484015260003073ffffffffffffffffffffffffffffffffffffffff1684604051611c6b919061366d565b600060405180830381855af49150503d8060008114611ca6576040519150601f19603f3d011682016040523d82523d6000602084013e611cab565b606091505b5050905080611918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e61626c6520746f206372656174652072657175657374000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052610c349060540160405160208183030381529060405280519060200120848484611685565b611d78612353565b611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b80611e45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e646572000000000060448201526064016105ba565b60015460005b81811015611eda57600080600060018481548110611e6b57611e6b6134f3565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ed381613551565b9050611e4b565b5060005b8281101561203057600080858584818110611efb57611efb6134f3565b9050602002016020810190611f1091906134a3565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615611fa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e646572730060448201526064016105ba565b6001600080868685818110611fb857611fb86134f3565b9050602002016020810190611fcd91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561202981613551565b9050611ede565b5061203d60018484612d4c565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516120719392919061378c565b60405180910390a1505050565b6120866123a8565b61208f81612bbf565b50565b61209a6123a8565b80806120a461297a565b1015612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156121c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121eb91906136de565b61074e5761074e6137c6565b6121ff612353565b612265576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b7f1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727848484843360405161229c9594939291906137f5565b60405180910390a160005b83811015610968578484828181106122c1576122c16134f3565b90506020020160208101906122d691906134a3565b73ffffffffffffffffffffffffffffffffffffffff1663ee56997b84846040518363ffffffff1660e01b8152600401612310929190613845565b600060405180830381600087803b15801561232a57600080fd5b505af115801561233e573d6000803e3d6000fd5b505050508061234c90613551565b90506122a7565b3360009081526020819052604081205460ff168061104357503361238c60025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60025473ffffffffffffffffffffffffffffffffffffffff163314612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105ba565b565b600080857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b16602082015260348101869052605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206000818152600490935291205490935060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016156125ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d75737420757365206120756e6971756520494400000000000000000000000060448201526064016105ba565b6125fb61012c42613861565b6040805160208082018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16828401527fffffffff000000000000000000000000000000000000000000000000000000008a1660548301526058808301859052835180840390910181526078909201909252805191012090925060405180604001604052808260ff1916815260200161269a87612cb5565b60ff9081169091526000868152600460209081526040909120835193909101519091167f01000000000000000000000000000000000000000000000000000000000000000260089290921c9190911790556006546126f9908a90613861565b6006555050965096945050505050565b3360009081526020819052604090205460ff16612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e646572000000000000000000000060448201526064016105ba565b6040805160208082018890527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16828401527fffffffff00000000000000000000000000000000000000000000000000000000861660548301526058808301869052835180840390910181526078909201909252805191012060009060008881526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146128a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b6128af82612cb5565b60008881526004602052604090205460ff9182167f01000000000000000000000000000000000000000000000000000000000000009091049091161115612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f446174612076657273696f6e73206d757374206d61746368000000000000000060448201526064016105ba565b8560065461296091906136c5565b600655505050600093845250506004602052506040812055565b6000600160065461298b91906136c5565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190613874565b61104391906136c5565b612a4f6002602061388d565b612a5a906004613861565b81511015612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642072657175657374206c656e6774680000000000000000000060448201526064016105ba565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f3c6d41b9000000000000000000000000000000000000000000000000000000001480612b5557507fffffffff0000000000000000000000000000000000000000000000000000000082167f4042994600000000000000000000000000000000000000000000000000000000145b612bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d757374207573652077686974656c69737465642066756e6374696f6e73000060448201526064016105ba565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603612c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105ba565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b600060ff821115612d48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203860448201527f206269747300000000000000000000000000000000000000000000000000000060648201526084016105ba565b5090565b828054828255906000526020600020908101928215612dc4579160200282015b82811115612dc45781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190612d6c565b50612d489291505b80821115612d485760008155600101612dcc565b60008083601f840112612df257600080fd5b50813567ffffffffffffffff811115612e0a57600080fd5b6020830191508360208260051b8501011115612e2557600080fd5b9250929050565b60008060208385031215612e3f57600080fd5b823567ffffffffffffffff811115612e5657600080fd5b612e6285828601612de0565b90969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461208f57600080fd5b60008083601f840112612ea257600080fd5b50813567ffffffffffffffff811115612eba57600080fd5b602083019150836020828501011115612e2557600080fd5b600080600060408486031215612ee757600080fd5b8335612ef281612e6e565b9250602084013567ffffffffffffffff811115612f0e57600080fd5b612f1a86828701612e90565b9497909650939450505050565b60005b83811015612f42578181015183820152602001612f2a565b50506000910152565b6020815260008251806020840152612f6a816040850160208701612f27565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b81811015612fea57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fb8565b50909695505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461302657600080fd5b919050565b60008060008060008060008060e0898b03121561304757600080fd5b883561305281612e6e565b9750602089013596506040890135955061306e60608a01612ff6565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561309857600080fd5b6130a48b828c01612e90565b999c989b5096995094979396929594505050565b6000806000604084860312156130cd57600080fd5b833567ffffffffffffffff8111156130e457600080fd5b6130f086828701612de0565b909450925050602084013561310481612e6e565b809150509250925092565b60008060008060008060008060006101008a8c03121561312e57600080fd5b893561313981612e6e565b985060208a0135975060408a0135965060608a013561315781612e6e565b955061316560808b01612ff6565b945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff81111561318f57600080fd5b61319b8c828d01612e90565b915080935050809150509295985092959850929598565b60008060008060008060c087890312156131cb57600080fd5b863595506020870135945060408701356131e481612e6e565b93506131f260608801612ff6565b92506080870135915060a087013590509295509295509295565b6000806000806040858703121561322257600080fd5b843567ffffffffffffffff8082111561323a57600080fd5b61324688838901612de0565b9096509450602087013591508082111561325f57600080fd5b5061326c87828801612de0565b95989497509550505050565b600080600080600080600060c0888a03121561329357600080fd5b873596506020880135955060408801356132ac81612e6e565b94506132ba60608901612ff6565b93506080880135925060a088013567ffffffffffffffff8111156132dd57600080fd5b6132e98a828b01612e90565b989b979a50959850939692959293505050565b6000806000806080858703121561331257600080fd5b843593506020850135925061332960408601612ff6565b9396929550929360600135925050565b6000806000806060858703121561334f57600080fd5b843561335a81612e6e565b935060208501359250604085013567ffffffffffffffff81111561337d57600080fd5b61326c87828801612e90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156133cd57600080fd5b83356133d881612e6e565b925060208401359150604084013567ffffffffffffffff808211156133fc57600080fd5b818601915086601f83011261341057600080fd5b81358181111561342257613422613389565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561346857613468613389565b8160405282815289602084870101111561348157600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156134b557600080fd5b81356134c081612e6e565b9392505050565b600080604083850312156134da57600080fd5b82356134e581612e6e565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361358257613582613522565b5060010190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010073ffffffffffffffffffffffffffffffffffffffff808d1684528b60208501528a6040850152808a166060850152507fffffffff00000000000000000000000000000000000000000000000000000000881660808401528660a08401528560c08401528060e084015261365d8184018587613599565b9c9b505050505050505050505050565b6000825161367f818460208701612f27565b9190910192915050565b7fffffffff0000000000000000000000000000000000000000000000000000000084168152818360048301376000910160040190815292915050565b818103818111156136d8576136d8613522565b92915050565b6000602082840312156136f057600080fd5b815180151581146134c057600080fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611b7e606083018486613599565b8183526000602080850194508260005b8581101561378157813561375981612e6e565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613746565b509495945050505050565b6040815260006137a0604083018587613736565b905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b606081526000613809606083018789613736565b828103602084015261381c818688613736565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b602081526000613859602083018486613736565b949350505050565b808201808211156136d8576136d8613522565b60006020828403121561388657600080fd5b5051919050565b80820281158282048414176136d8576136d861352256fea164736f6c6343000813000a60a06040523480156200001157600080fd5b50604051620016993803806200169983398101604081905262000034916200029d565b82826001600160a01b038216620000925760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c557620000c58162000199565b50506001600160a01b0384166200012b5760405162461bcd60e51b815260206004820152602360248201527f4c696e6b20746f6b656e2063616e6e6f742062652061207a65726f206164647260448201526265737360e81b606482015260840162000089565b6001600160a01b038085166080528216156200018f57816001600160a01b0316836001600160a01b03167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e836040516200018691906200038e565b60405180910390a35b50505050620003c3565b336001600160a01b03821603620001f35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000089565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200025c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002945781810151838201526020016200027a565b50506000910152565b60008060008060808587031215620002b457600080fd5b620002bf8562000244565b9350620002cf6020860162000244565b9250620002df6040860162000244565b60608601519092506001600160401b0380821115620002fd57600080fd5b818701915087601f8301126200031257600080fd5b81518181111562000327576200032762000261565b604051601f8201601f19908116603f0116810190838211818310171562000352576200035262000261565b816040528281528a60208487010111156200036c57600080fd5b6200037f83602083016020880162000277565b979a9699509497505050505050565b6020815260008251806020840152620003af81604085016020870162000277565b601f01601f19169190910160400192915050565b6080516112ac620003ed6000396000818161016d0152818161037501526105d301526112ac6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063ee56997b1161005b578063ee56997b14610200578063f2fde38b14610213578063fa00763a1461022657600080fd5b806379ba5097146101c75780638da5cb5b146101cf578063b64fa9e6146101ed57600080fd5b80634d3e2323116100b25780634d3e23231461015557806357970e93146101685780636fadcf72146101b457600080fd5b8063033f49f7146100d9578063181f5a77146100ee5780632408afaa14610140575b600080fd5b6100ec6100e7366004610e72565b61026f565b005b61012a6040518060400160405280601981526020017f417574686f72697a6564466f7277617264657220312e312e300000000000000081525081565b6040516101379190610ef5565b60405180910390f35b610148610287565b6040516101379190610f61565b6100ec610163366004610e72565b6102f6565b61018f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610137565b6100ec6101c2366004610e72565b61036b565b6100ec61042d565b60005473ffffffffffffffffffffffffffffffffffffffff1661018f565b6100ec6101fb366004611007565b61052a565b6100ec61020e366004611073565b6106cb565b6100ec6102213660046110b5565b6109dc565b61025f6102343660046110b5565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460ff1690565b6040519015158152602001610137565b6102776109f0565b610282838383610a73565b505050565b606060038054806020026020016040519081016040528092919081815260200182805480156102ec57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102c1575b5050505050905090565b6102ff836109dc565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e848460405161035e9291906110d7565b60405180910390a3505050565b610373610c00565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e0000000060448201526064015b60405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff1633146104ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610424565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610532610c00565b82811461059b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f417272617973206d7573742068617665207468652073616d65206c656e6774686044820152606401610424565b60005b838110156106c45760008585838181106105ba576105ba611124565b90506020020160208101906105cf91906110b5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e000000006044820152606401610424565b6106b38185858581811061069c5761069c611124565b90506020028101906106ae9190611153565b610a73565b506106bd816111b8565b905061059e565b5050505050565b6106d3610c79565b610739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e646572730000006044820152606401610424565b806107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e64657200000000006044820152606401610424565b60035460005b8181101561083657600060026000600384815481106107c7576107c7611124565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082f816111b8565b90506107a6565b5060005b8281101561098e576002600085858481811061085857610858611124565b905060200201602081019061086d91906110b5565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156108fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e64657273006044820152606401610424565b60016002600086868581811061091657610916611124565b905060200201602081019061092b91906110b5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610987816111b8565b905061083a565b5061099b60038484610dac565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516109cf93929190611217565b60405180910390a1505050565b6109e46109f0565b6109ed81610cb7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610424565b565b73ffffffffffffffffffffffffffffffffffffffff83163b610af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e74726163740000000000006044820152606401610424565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610b1b92919061128f565b6000604051808303816000865af19150503d8060008114610b58576040519150601f19603f3d011682016040523d82523d6000602084013e610b5d565b606091505b5091509150816106c4578051600003610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f466f727761726465642063616c6c20726576657274656420776974686f75742060448201527f726561736f6e00000000000000000000000000000000000000000000000000006064820152608401610424565b805181602001fd5b3360009081526002602052604090205460ff16610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e64657200000000000000000000006044820152606401610424565b600033610c9b60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b3373ffffffffffffffffffffffffffffffffffffffff821603610d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610424565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e24579160200282015b82811115610e245781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610dcc565b50610e30929150610e34565b5090565b5b80821115610e305760008155600101610e35565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b919050565b600080600060408486031215610e8757600080fd5b610e9084610e49565b9250602084013567ffffffffffffffff80821115610ead57600080fd5b818601915086601f830112610ec157600080fd5b813581811115610ed057600080fd5b876020828501011115610ee257600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610faf57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f7d565b50909695505050505050565b60008083601f840112610fcd57600080fd5b50813567ffffffffffffffff811115610fe557600080fd5b6020830191508360208260051b850101111561100057600080fd5b9250929050565b6000806000806040858703121561101d57600080fd5b843567ffffffffffffffff8082111561103557600080fd5b61104188838901610fbb565b9096509450602087013591508082111561105a57600080fd5b5061106787828801610fbb565b95989497509550505050565b6000806020838503121561108657600080fd5b823567ffffffffffffffff81111561109d57600080fd5b6110a985828601610fbb565b90969095509350505050565b6000602082840312156110c757600080fd5b6110d082610e49565b9392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118857600080fd5b83018035915067ffffffffffffffff8211156111a357600080fd5b60200191503681900382131561100057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611210577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6040808252810183905260008460608301825b868110156112655773ffffffffffffffffffffffffffffffffffffffff61125084610e49565b1682526020928301929091019060010161122a565b50809250505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b818382376000910190815291905056fea164736f6c6343000813000aa164736f6c6343000813000a", +} + +var OperatorFactoryABI = OperatorFactoryMetaData.ABI + +var OperatorFactoryBin = OperatorFactoryMetaData.Bin + +func DeployOperatorFactory(auth *bind.TransactOpts, backend bind.ContractBackend, linkAddress common.Address) (common.Address, *types.Transaction, *OperatorFactory, error) { + parsed, err := OperatorFactoryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OperatorFactoryBin), backend, linkAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OperatorFactory{address: address, abi: *parsed, OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil +} + +type OperatorFactory struct { + address common.Address + abi abi.ABI + OperatorFactoryCaller + OperatorFactoryTransactor + OperatorFactoryFilterer +} + +type OperatorFactoryCaller struct { + contract *bind.BoundContract +} + +type OperatorFactoryTransactor struct { + contract *bind.BoundContract +} + +type OperatorFactoryFilterer struct { + contract *bind.BoundContract +} + +type OperatorFactorySession struct { + Contract *OperatorFactory + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OperatorFactoryCallerSession struct { + Contract *OperatorFactoryCaller + CallOpts bind.CallOpts +} + +type OperatorFactoryTransactorSession struct { + Contract *OperatorFactoryTransactor + TransactOpts bind.TransactOpts +} + +type OperatorFactoryRaw struct { + Contract *OperatorFactory +} + +type OperatorFactoryCallerRaw struct { + Contract *OperatorFactoryCaller +} + +type OperatorFactoryTransactorRaw struct { + Contract *OperatorFactoryTransactor +} + +func NewOperatorFactory(address common.Address, backend bind.ContractBackend) (*OperatorFactory, error) { + abi, err := abi.JSON(strings.NewReader(OperatorFactoryABI)) + if err != nil { + return nil, err + } + contract, err := bindOperatorFactory(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OperatorFactory{address: address, abi: abi, OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil +} + +func NewOperatorFactoryCaller(address common.Address, caller bind.ContractCaller) (*OperatorFactoryCaller, error) { + contract, err := bindOperatorFactory(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OperatorFactoryCaller{contract: contract}, nil +} + +func NewOperatorFactoryTransactor(address common.Address, transactor bind.ContractTransactor) (*OperatorFactoryTransactor, error) { + contract, err := bindOperatorFactory(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OperatorFactoryTransactor{contract: contract}, nil +} + +func NewOperatorFactoryFilterer(address common.Address, filterer bind.ContractFilterer) (*OperatorFactoryFilterer, error) { + contract, err := bindOperatorFactory(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OperatorFactoryFilterer{contract: contract}, nil +} + +func bindOperatorFactory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OperatorFactoryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OperatorFactory *OperatorFactoryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OperatorFactory.Contract.OperatorFactoryCaller.contract.Call(opts, result, method, params...) +} + +func (_OperatorFactory *OperatorFactoryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.Contract.OperatorFactoryTransactor.contract.Transfer(opts) +} + +func (_OperatorFactory *OperatorFactoryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OperatorFactory.Contract.OperatorFactoryTransactor.contract.Transact(opts, method, params...) +} + +func (_OperatorFactory *OperatorFactoryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OperatorFactory.Contract.contract.Call(opts, result, method, params...) +} + +func (_OperatorFactory *OperatorFactoryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.Contract.contract.Transfer(opts) +} + +func (_OperatorFactory *OperatorFactoryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OperatorFactory.Contract.contract.Transact(opts, method, params...) +} + +func (_OperatorFactory *OperatorFactoryCaller) Created(opts *bind.CallOpts, query common.Address) (bool, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "created", query) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) Created(query common.Address) (bool, error) { + return _OperatorFactory.Contract.Created(&_OperatorFactory.CallOpts, query) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) Created(query common.Address) (bool, error) { + return _OperatorFactory.Contract.Created(&_OperatorFactory.CallOpts, query) +} + +func (_OperatorFactory *OperatorFactoryCaller) LinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "linkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) LinkToken() (common.Address, error) { + return _OperatorFactory.Contract.LinkToken(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) LinkToken() (common.Address, error) { + return _OperatorFactory.Contract.LinkToken(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) TypeAndVersion() (string, error) { + return _OperatorFactory.Contract.TypeAndVersion(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) TypeAndVersion() (string, error) { + return _OperatorFactory.Contract.TypeAndVersion(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewForwarder(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewForwarder") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewForwarderAndTransferOwnership(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewForwarderAndTransferOwnership", to, message) +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewForwarderAndTransferOwnership(to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarderAndTransferOwnership(&_OperatorFactory.TransactOpts, to, message) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewForwarderAndTransferOwnership(to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarderAndTransferOwnership(&_OperatorFactory.TransactOpts, to, message) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewOperator(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewOperator") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewOperator() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperator(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewOperator() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperator(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewOperatorAndForwarder(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewOperatorAndForwarder") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperatorAndForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperatorAndForwarder(&_OperatorFactory.TransactOpts) +} + +type OperatorFactoryAuthorizedForwarderCreatedIterator struct { + Event *OperatorFactoryAuthorizedForwarderCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryAuthorizedForwarderCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryAuthorizedForwarderCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Error() error { + return it.fail +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorFactoryAuthorizedForwarderCreated struct { + Forwarder common.Address + Owner common.Address + Sender common.Address + Raw types.Log +} + +func (_OperatorFactory *OperatorFactoryFilterer) FilterAuthorizedForwarderCreated(opts *bind.FilterOpts, forwarder []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryAuthorizedForwarderCreatedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.FilterLogs(opts, "AuthorizedForwarderCreated", forwarderRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return &OperatorFactoryAuthorizedForwarderCreatedIterator{contract: _OperatorFactory.contract, event: "AuthorizedForwarderCreated", logs: logs, sub: sub}, nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) WatchAuthorizedForwarderCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryAuthorizedForwarderCreated, forwarder []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.WatchLogs(opts, "AuthorizedForwarderCreated", forwarderRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorFactoryAuthorizedForwarderCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "AuthorizedForwarderCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) ParseAuthorizedForwarderCreated(log types.Log) (*OperatorFactoryAuthorizedForwarderCreated, error) { + event := new(OperatorFactoryAuthorizedForwarderCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "AuthorizedForwarderCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorFactoryOperatorCreatedIterator struct { + Event *OperatorFactoryOperatorCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorFactoryOperatorCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryOperatorCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryOperatorCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorFactoryOperatorCreatedIterator) Error() error { + return it.fail +} + +func (it *OperatorFactoryOperatorCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorFactoryOperatorCreated struct { + Operator common.Address + Owner common.Address + Sender common.Address + Raw types.Log +} + +func (_OperatorFactory *OperatorFactoryFilterer) FilterOperatorCreated(opts *bind.FilterOpts, operator []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryOperatorCreatedIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.FilterLogs(opts, "OperatorCreated", operatorRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return &OperatorFactoryOperatorCreatedIterator{contract: _OperatorFactory.contract, event: "OperatorCreated", logs: logs, sub: sub}, nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) WatchOperatorCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryOperatorCreated, operator []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.WatchLogs(opts, "OperatorCreated", operatorRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorFactoryOperatorCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "OperatorCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) ParseOperatorCreated(log types.Log) (*OperatorFactoryOperatorCreated, error) { + event := new(OperatorFactoryOperatorCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "OperatorCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_OperatorFactory *OperatorFactory) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OperatorFactory.abi.Events["AuthorizedForwarderCreated"].ID: + return _OperatorFactory.ParseAuthorizedForwarderCreated(log) + case _OperatorFactory.abi.Events["OperatorCreated"].ID: + return _OperatorFactory.ParseOperatorCreated(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OperatorFactoryAuthorizedForwarderCreated) Topic() common.Hash { + return common.HexToHash("0x1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b") +} + +func (OperatorFactoryOperatorCreated) Topic() common.Hash { + return common.HexToHash("0xd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab") +} + +func (_OperatorFactory *OperatorFactory) Address() common.Address { + return _OperatorFactory.address +} + +type OperatorFactoryInterface interface { + Created(opts *bind.CallOpts, query common.Address) (bool, error) + + LinkToken(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + DeployNewForwarder(opts *bind.TransactOpts) (*types.Transaction, error) + + DeployNewForwarderAndTransferOwnership(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) + + DeployNewOperator(opts *bind.TransactOpts) (*types.Transaction, error) + + DeployNewOperatorAndForwarder(opts *bind.TransactOpts) (*types.Transaction, error) + + FilterAuthorizedForwarderCreated(opts *bind.FilterOpts, forwarder []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryAuthorizedForwarderCreatedIterator, error) + + WatchAuthorizedForwarderCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryAuthorizedForwarderCreated, forwarder []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) + + ParseAuthorizedForwarderCreated(log types.Log) (*OperatorFactoryAuthorizedForwarderCreated, error) + + FilterOperatorCreated(opts *bind.FilterOpts, operator []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryOperatorCreatedIterator, error) + + WatchOperatorCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryOperatorCreated, operator []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) + + ParseOperatorCreated(log types.Log) (*OperatorFactoryOperatorCreated, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt new file mode 100644 index 00000000000..1569801b3fb --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -0,0 +1,6 @@ +GETH_VERSION: 1.13.8 +authorized_forwarder: ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10 +authorized_receiver: ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin 18e8969ba3234b027e1b16c11a783aca58d0ea5c2361010ec597f134b7bf1c4f +link_token_receiver: ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.abi ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.bin 839552e2bea179bdf2591805422fb33769c1646d5a014a00fc2c0cd9c03ef229 +operator: ../../../contracts/solc/v0.8.19/Operator/Operator.abi ../../../contracts/solc/v0.8.19/Operator/Operator.bin 23c3888eaa7259e6adf2153d09abae8f4b1987dc44200363faab1e65483f32d5 +operator_factory: ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 88e6baa5d9b255eea02616fbcb2cbe21a25ab46adeb6395f6289d169dec949ae diff --git a/core/gethwrappers/operatorforwarder/go_generate.go b/core/gethwrappers/operatorforwarder/go_generate.go new file mode 100644 index 00000000000..074eccdaf4d --- /dev/null +++ b/core/gethwrappers/operatorforwarder/go_generate.go @@ -0,0 +1,10 @@ +// Package gethwrappers provides tools for wrapping solidity contracts with +// golang packages, using abigen. +package gethwrappers + +// Chainlink Operator Forwarder contracts +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin AuthorizedForwarder authorized_forwarder +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin AuthorizedReceiver authorized_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.abi ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.bin LinkTokenReceiver link_token_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Operator/Operator.abi ../../../contracts/solc/v0.8.19/Operator/Operator.bin Operator operator +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin OperatorFactory operator_factory From 29b16360fb41e4372f72fe744aaf3ee8234a9b67 Mon Sep 17 00:00:00 2001 From: Lei Date: Fri, 3 May 2024 10:49:28 -0700 Subject: [PATCH 15/35] get available erc20 for finance payment (#13088) --- .changeset/tall-hats-brake.md | 5 ++++ contracts/.changeset/proud-tables-grab.md | 5 ++++ .../v2_3/IAutomationRegistryMaster2_3.sol | 5 ++-- .../dev/test/AutomationRegistry2_3.t.sol | 19 ++++++++++++++ .../dev/v2_3/AutomationRegistryLogicC2_3.sol | 7 +++++ ..._automation_registry_master_wrapper_2_3.go | 26 ++++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 .changeset/tall-hats-brake.md create mode 100644 contracts/.changeset/proud-tables-grab.md diff --git a/.changeset/tall-hats-brake.md b/.changeset/tall-hats-brake.md new file mode 100644 index 00000000000..1c11e4baeca --- /dev/null +++ b/.changeset/tall-hats-brake.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +get available erc20 for payment #bugfix diff --git a/contracts/.changeset/proud-tables-grab.md b/contracts/.changeset/proud-tables-grab.md new file mode 100644 index 00000000000..f2799f86ee9 --- /dev/null +++ b/contracts/.changeset/proud-tables-grab.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +get available erc20s for payment #bugfix diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index c0952963366..01b19cb480f 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -1,4 +1,4 @@ -// abi-checksum: 0x2cc33080c864676d572ad7ae658ea4a4621b3fd4c4664d84f9945b2324348434 +// abi-checksum: 0xa0e676f1c24f6a43a512fe7141593fb4d4cd6b16c5dcdb0bca2c32e9b135f58a // SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! pragma solidity ^0.8.4; @@ -228,6 +228,7 @@ interface IAutomationRegistryMaster2_3 { function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); function getAllowedReadOnlyAddress() external view returns (address); function getAutomationForwarderLogic() external view returns (address); + function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); function getBalance(uint256 id) external view returns (uint96 balance); function getBillingConfig( address billingToken @@ -417,5 +418,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 6da98e16fe5..ca4075a59c7 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -205,6 +205,7 @@ contract AddFunds is SetUp { registry.addFunds(nativeUpkeepID, 1); assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); } // when msg.value is not 0, it uses the native payment path @@ -214,6 +215,7 @@ contract AddFunds is SetUp { registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); } // it fails when the billing token is not native, but trying to pay with native @@ -348,6 +350,10 @@ contract Withdraw is SetUp { function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); vm.prank(FINANCE_ADMIN); registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert @@ -1563,8 +1569,21 @@ contract Transmit is SetUp { upkeepIDs[0] = linkUpkeepID; upkeepIDs[1] = usdUpkeepID18; upkeepIDs[2] = nativeUpkeepID; + + // withdraw-able by finance team should be 0 + require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); + require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); + // do the thing _transmit(upkeepIDs, registry); + + // withdraw-able by the finance team should be positive + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); + // assert upkeep balances have decreased require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index d4565615ad1..838e05353c8 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -584,6 +584,13 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { return s_reserveAmounts[billingToken]; } + /** + * @notice returns the amount of a particular token that is withdraw-able by finance admin + */ + function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { + return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; + } + /** * @notice returns the size of the LINK liquidity pool */ diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index cdbb52883ff..2c44939a9a0 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -139,7 +139,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -472,6 +472,28 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetAutomationForwarderLogic(&_IAutomationRegistryMaster23.CallOpts) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getAvailableERC20ForPayment", billingToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _IAutomationRegistryMaster23.Contract.GetAvailableERC20ForPayment(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _IAutomationRegistryMaster23.Contract.GetAvailableERC20ForPayment(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBalance", id) @@ -7308,6 +7330,8 @@ type IAutomationRegistryMaster23Interface interface { GetAutomationForwarderLogic(opts *bind.CallOpts) (common.Address, error) + GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) + GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d5a931321ab..9dbf6e87090 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 19f51996d05341f1229f21be26b5d72ff58e321f0b6da69c260f768e4622ae8e +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin aa65a3c4bc89fadae2f389da6643caad50e9b9948d61e2d40d8f00774f356a80 i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 From a34a17ae9d62679a1ff15a7703f5cbcf6dfd1d0f Mon Sep 17 00:00:00 2001 From: Lei Date: Fri, 3 May 2024 11:43:21 -0700 Subject: [PATCH 16/35] finance can withdraw erc20s in offchain mode (#13058) --- .changeset/grumpy-birds-serve.md | 5 ++ contracts/.changeset/calm-maps-vanish.md | 5 ++ .../dev/test/AutomationRegistry2_3.t.sol | 61 ++++++++++++++++++- .../dev/v2_3/AutomationRegistryLogicB2_3.sol | 4 +- ...automation_registry_logic_b_wrapper_2_3.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 .changeset/grumpy-birds-serve.md create mode 100644 contracts/.changeset/calm-maps-vanish.md diff --git a/.changeset/grumpy-birds-serve.md b/.changeset/grumpy-birds-serve.md new file mode 100644 index 00000000000..35b2c160c02 --- /dev/null +++ b/.changeset/grumpy-birds-serve.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +withdraw in offchain mode #bugfix diff --git a/contracts/.changeset/calm-maps-vanish.md b/contracts/.changeset/calm-maps-vanish.md new file mode 100644 index 00000000000..e9dfcdd53b0 --- /dev/null +++ b/contracts/.changeset/calm-maps-vanish.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +withdraw in offchain mode #bugfix diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index ca4075a59c7..5611b11acf0 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -347,6 +347,7 @@ contract Withdraw is SetUp { registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds } + // default is ON_CHAIN mode function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); @@ -362,6 +363,27 @@ contract Withdraw is SetUp { registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw } + function test_WithdrawERC20Fees_InOffChainMode_Happy() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw + + // recipient should get the funds + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + } + function testWithdrawERC20FeeSuccess() public { // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); @@ -965,7 +987,8 @@ contract NOPsSettlement is SetUp { registry.settleNOPsOffchain(); } - function testSettleNOPsOffchainSuccessTransmitterBalanceZeroed() public { + // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same + function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { // deploy and configure a registry with OFF_CHAIN payout (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); @@ -1007,6 +1030,42 @@ contract NOPsSettlement is SetUp { // after the offchain settlement, the total reserve amount of LINK should be 0 assertEq(registry.getReserveAmount(address(linkToken)), 0); + // should have some ERC20s in registry after transmit + uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); + + vm.startPrank(UPKEEP_ADMIN); + vm.roll(100 + block.number); + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); + + // finance admin comes to withdraw all available ERC20s + vm.startPrank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); + + uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); + + uint256 reservedLink = registry.getReserveAmount(address(linkToken)); + require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); + + // owner comes to disable offchain mode + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity + vm.startPrank(FINANCE_ADMIN); + uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); + + // reserved link amount to NOPs should stay the same after switching to onchain mode + assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); + // available ERC20 for payment should be 0 since finance admin withdrew all already + assertEq(erc20ForPayment4, 0); } function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol index d69d5e0bd96..dbdc563d9ba 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol @@ -430,14 +430,14 @@ contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { * @param asset the asset to withdraw * @param to the address to send the fees to * @param amount the amount to withdraw - * @dev we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity + * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity * to cover all outstanding debts on the registry */ function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { _onlyFinanceAdminAllowed(); if (to == ZERO_ADDRESS) revert InvalidRecipient(); if (address(asset) == address(i_link)) revert InvalidToken(); - if (_linkAvailableForPayment() < 0) revert InsufficientLinkLiquidity(); + if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; if (amount > available) revert InsufficientBalance(available, amount); diff --git a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go index 04087c52e11..7e7c893d4d0 100644 --- a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go @@ -46,7 +46,7 @@ type AutomationRegistryBase23BillingOverrides struct { var AutomationRegistryLogicBMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicC2_3\",\"name\":\"logicC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162005c0e38038062005c0e83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516154d46200073a60003960008181610182015261022f0152600081816120c5015261226b01526000612b910152600050506000612ec701526000613c3b01526000612fa1015260008181610c4701528181610d0801528181610dd30152612c5201526154d46000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e236600461437c565b610511565b3480156101f357600080fd5b506102076102023660046144f0565b610617565b604051610217949392919061460f565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f366004614691565b6108f5565b3480156102a057600080fd5b506101c56102af3660046146dd565b610957565b3480156102c057600080fd5b506101c56102cf3660046146f6565b610b09565b3480156102e057600080fd5b506101c56102ef366004614722565b610d7c565b34801561030057600080fd5b5061031461030f3660046144f0565b611008565b6040516102179796959493929190614763565b34801561033357600080fd5b506101c56103423660046146dd565b61176c565b34801561035357600080fd5b506101c561036236600461437c565b611802565b34801561037357600080fd5b506101c5611c7a565b34801561038857600080fd5b506101c56103973660046146dd565b611d77565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e2366004614691565b611f2c565b6101c56103f53660046147b1565b611f81565b34801561040657600080fd5b506101c56104153660046147f9565b612343565b34801561042657600080fd5b506101c561043536600461481e565b612442565b34801561044657600080fd5b5061045a610455366004614691565b612523565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046146dd565b6126ce565b34801561049d57600080fd5b506101c56104ac366004614691565b6128fb565b3480156104bd57600080fd5b506102076104cc366004614898565b6129b2565b3480156104dd57600080fd5b506101c56104ec36600461497a565b612a74565b3480156104fd57600080fd5b5061031461050c3660046146dd565b612a88565b61051a82612ac4565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b79565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e091906149c4565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614a0f565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614a77565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ac4565b6000838152601d60205260409020610917828483614b5c565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614cc0565b60405180910390a2505050565b61096081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612bea565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c50565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614cd4565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c50565b1215610e98576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190614cef565b610f429190614a0f565b905080821115610f88576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fa973ffffffffffffffffffffffffffffffffffffffff85168484612d1f565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061101c612b79565b60006110278a612df8565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a00151156113ea5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611760915050565b606083015163ffffffff908116146114345750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611760915050565b8251156114735750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611760915050565b61147c84612ea3565b8094508198508299505050506114a18e858786604001518b8b888a6101000151613095565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115035750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611760915050565b505060006115128d858e613405565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158d91906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115cd91906149c4565b60006040518083038160008787f1925050503d806000811461160b576040519150601f19603f3d011682016040523d82523d6000602084013e611610565b606091505b50915091505a611620908b614a0f565b9950816116a6576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116855750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611760915050565b604090930151929a50600399505063ffffffff909116955061176092505050565b808060200190518101906116ba9190614a77565b909d509b508c6116f45750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611760915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101561174e5750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611760915050565b5050506040015163ffffffff16945050505b92959891949750929550565b6117746135e5565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561185a576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff81166118e9576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a29576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abd9190614cef565b816060015163ffffffff161115611b00576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b6b908290614a0f565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611bee9116846bffffffffffffffffffffffff8416612d1f565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611d8081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611eba576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611efc600283613636565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f3583612ac4565b6000838152601e60205260409020611f4e828483614b5c565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614cc0565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120bd576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415612159577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461214d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215634613642565b91505b818160c001516121699190614d08565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff16835260219091529020546121f991841690614d2d565b61010082015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040812091909155349003612269576101008101516122649073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff86166136e4565b6122f9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff161080612380575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123b7576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123c082612ac4565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61244a6135e5565b6000828152600460205260409020546601000000000000900463ffffffff908116146124a2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906124f08282614d51565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124369190614dd8565b60008061252e612b79565b601454760100000000000000000000000000000000000000000000900460ff1615612585576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126c193899089908190840183828082843760009201919091525061374892505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461280a576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612867576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61290483612ac4565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612966576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260076020526040902061297f828483614b5c565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614cc0565b600060606000806000634b56a42e60e01b8888886040516024016129d893929190614e0f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a618982610617565b929c919b50995090975095505050505050565b612a7c613963565b612a85816139e4565b50565b600060606000806000806000612aad8860405180602001604052806000815250611008565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b21576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612a85576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612be8576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612bf68383613ad9565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d109190614cef565b612d1a9190614ea5565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612df39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b28565b505050565b6000818160045b600f811015612e85577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e3d57612e3d614ec5565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e7357506000949350505050565b80612e7d81614ef4565b915050612dff565b5081600f1a6001811115612e9b57612e9b6145a5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190614f46565b5094509092505050600081131580612f6b57508142105b80612f8c5750828015612f8c5750612f838242614a0f565b8463ffffffff16105b15612f9b576019549650612f9f565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561300a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302e9190614f46565b509450909250505060008113158061304557508142105b806130665750828015613066575061305d8242614a0f565b8463ffffffff16105b1561307557601a549550613079565b8095505b86866130848a613c34565b965096509650505050509193909250565b60008080808960018111156130ac576130ac6145a5565b036130bb575062016b48613110565b60018960018111156130cf576130cf6145a5565b036130de57506201ccf0613110565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131239190614f96565b6131319060ff166040614faf565b60185461315f906103a49074010000000000000000000000000000000000000000900463ffffffff16614d2d565b6131699190614d2d565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fe9190614fc6565b90925090508183613210836018614d2d565b61321a9190614faf565b60808f015161322a906001614f96565b6132399060ff166115e0614faf565b6132439190614d2d565b61324d9190614d2d565b6132579085614d2d565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ee9190614cef565b8d6060015161ffff166133019190614faf565b945050505060006133128b86613d25565b60008d815260046020526040902054909150610100900460ff16156133775760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006133e18c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ea1565b602081015181519192506133f491614d08565b9d9c50505050505050505050505050565b6060600083600181111561341b5761341b6145a5565b036134e4576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161346091602401615085565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290506135de565b60018360018111156134f8576134f86145a5565b036130de5760008280602001905181019061351391906150fe565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161355891849160240161520e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506135de9050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bf683836140f6565b60006bffffffffffffffffffffffff8211156136e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137429085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d71565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137a5576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061381a9085906024016152d9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906138ed90879087906004016152ec565b60408051808303816000875af115801561390b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392f9190615305565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b2057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612bf9565b506000612bf9565b6000613b8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166141e99092919063ffffffff16565b805190915015612df35780806020019051810190613ba89190614cd4565b612df3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc89190614f46565b50935050925050600082131580613cde57508042105b80613d0e57506000846040015162ffffff16118015613d0e5750613d028142614a0f565b846040015162ffffff16105b15613d1e575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e369190614f46565b50935050925050600082131580613e4c57508042105b80613e7c57506000866040015162ffffff16118015613e7c5750613e708142614a0f565b866040015162ffffff16105b15613e905760018301546060850152613e98565b606084018290525b50505092915050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613eef9190614faf565b90508361010001518015613f025750803a105b15613f0a57503a5b600060128311613f1b576001613f31565b613f26601284614a0f565b613f3190600a615451565b9050600060128410613f44576001613f5a565b613f4f846012614a0f565b613f5a90600a615451565b905060008660a00151876040015188602001518960000151613f7c9190614d2d565b613f869087614faf565b613f909190614d2d565b613f9a9190614faf565b9050613fcc828860e0015160600151613fb39190614faf565b613fbd8584614faf565b613fc7919061545d565b613642565b6bffffffffffffffffffffffff1686526080870151613fef90613fc7908361545d565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906140289062ffffff16683635c9adc5dea00000614faf565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61405b9190614faf565b6140659190614d2d565b61406f9190614faf565b6140799190614faf565b614083919061545d565b61408d9190614d2d565b90506140b0848a60e00151606001516140a69190614faf565b613fbd8784614faf565b6bffffffffffffffffffffffff16602089015260808901516140d690613fc7908361545d565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b600081815260018301602052604081205480156141df57600061411a600183614a0f565b855490915060009061412e90600190614a0f565b905081811461419357600086600001828154811061414e5761414e614ec5565b906000526020600020015490508087600001848154811061417157614171614ec5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141a4576141a4615498565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612bf9565b6000915050612bf9565b6060612e9b8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161421d91906149c4565b60006040518083038185875af1925050503d806000811461425a576040519150601f19603f3d011682016040523d82523d6000602084013e61425f565b606091505b50915091506142708783838761427b565b979650505050505050565b6060831561431157825160000361430a5773ffffffffffffffffffffffffffffffffffffffff85163b61430a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612e9b565b612e9b83838151156143265781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906152d9565b73ffffffffffffffffffffffffffffffffffffffff81168114612a8557600080fd5b6000806040838503121561438f57600080fd5b8235915060208301356143a18161435a565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156143ff576143ff6143ac565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561444c5761444c6143ac565b604052919050565b600067ffffffffffffffff82111561446e5761446e6143ac565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126144ab57600080fd5b81356144be6144b982614454565b614405565b8181528460208386010111156144d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561450357600080fd5b82359150602083013567ffffffffffffffff81111561452157600080fd5b61452d8582860161449a565b9150509250929050565b60005b8381101561455257818101518382015260200161453a565b50506000910152565b60008151808452614573816020860160208601614537565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061460b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061462a608083018661455b565b905061463960408301856145d4565b82606083015295945050505050565b60008083601f84011261465a57600080fd5b50813567ffffffffffffffff81111561467257600080fd5b60208301915083602082850101111561468a57600080fd5b9250929050565b6000806000604084860312156146a657600080fd5b83359250602084013567ffffffffffffffff8111156146c457600080fd5b6146d086828701614648565b9497909650939450505050565b6000602082840312156146ef57600080fd5b5035919050565b6000806040838503121561470957600080fd5b82356147148161435a565b946020939093013593505050565b60008060006060848603121561473757600080fd5b83356147428161435a565b925060208401356147528161435a565b929592945050506040919091013590565b871515815260e06020820152600061477e60e083018961455b565b905061478d60408301886145d4565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156147c457600080fd5b8235915060208301356bffffffffffffffffffffffff811681146143a157600080fd5b63ffffffff81168114612a8557600080fd5b6000806040838503121561480c57600080fd5b8235915060208301356143a1816147e7565b600080828403606081121561483257600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561486657600080fd5b506020830190509250929050565b600067ffffffffffffffff82111561488e5761488e6143ac565b5060051b60200190565b600080600080606085870312156148ae57600080fd5b8435935060208086013567ffffffffffffffff808211156148ce57600080fd5b818801915088601f8301126148e257600080fd5b81356148f06144b982614874565b81815260059190911b8301840190848101908b83111561490f57600080fd5b8585015b838110156149475780358581111561492b5760008081fd5b6149398e89838a010161449a565b845250918601918601614913565b5097505050604088013592508083111561496057600080fd5b505061496e87828801614648565b95989497509550505050565b60006020828403121561498c57600080fd5b81356135de8161435a565b80516149a28161435a565b919050565b6000602082840312156149b957600080fd5b81516135de8161435a565b600082516149d6818460208701614537565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612bf957612bf96149e0565b805180151581146149a257600080fd5b600082601f830112614a4357600080fd5b8151614a516144b982614454565b818152846020838601011115614a6657600080fd5b612e9b826020830160208701614537565b60008060408385031215614a8a57600080fd5b614a9383614a22565b9150602083015167ffffffffffffffff811115614aaf57600080fd5b61452d85828601614a32565b600181811c90821680614acf57607f821691505b602082108103614b08577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612df357600081815260208120601f850160051c81016020861015614b355750805b601f850160051c820191505b81811015614b5457828155600101614b41565b505050505050565b67ffffffffffffffff831115614b7457614b746143ac565b614b8883614b828354614abb565b83614b0e565b6000601f841160018114614bda5760008515614ba45750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614c70565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c295786850135825560209485019460019092019101614c09565b5086821015614c64577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612e9b602083018486614c77565b600060208284031215614ce657600080fd5b612bf682614a22565b600060208284031215614d0157600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d1e57613d1e6149e0565b80820180821115612bf957612bf96149e0565b62ffffff81168114612a8557600080fd5b8135614d5c816147e7565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614d9c81614d40565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614de7816147e7565b63ffffffff1682526020830135614dfd81614d40565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614e84577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614e7286835161455b565b95509382019390820190600101614e38565b505085840381870152505050614e9b818587614c77565b9695505050505050565b8181036000831280158383131683831282161715613d1e57613d1e6149e0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f2557614f256149e0565b5060010190565b805169ffffffffffffffffffff811681146149a257600080fd5b600080600080600060a08688031215614f5e57600080fd5b614f6786614f2c565b9450602086015193506040860151925060608601519150614f8a60808701614f2c565b90509295509295909350565b60ff8181168382160190811115612bf957612bf96149e0565b8082028115828204841417612bf957612bf96149e0565b60008060408385031215614fd957600080fd5b505080516020909101519092909150565b60008154614ff781614abb565b808552602060018381168015615014576001811461504c5761507a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061507a565b866000528260002060005b858110156150725781548a8201860152908301908401615057565b890184019650505b505050505092915050565b602081526000612bf66020830184614fea565b600082601f8301126150a957600080fd5b815160206150b96144b983614874565b82815260059290921b840181019181810190868411156150d857600080fd5b8286015b848110156150f357805183529183019183016150dc565b509695505050505050565b60006020828403121561511057600080fd5b815167ffffffffffffffff8082111561512857600080fd5b90830190610100828603121561513d57600080fd5b6151456143db565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261517d60a08401614997565b60a082015260c08301518281111561519457600080fd5b6151a087828601615098565b60c08301525060e0830151828111156151b857600080fd5b6151c487828601614a32565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015615203578151875295820195908201906001016151e7565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c084015161010080818501525061527f6101408401826151d3565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526152bb828261455b565b91505082810360208401526152d08185614fea565b95945050505050565b602081526000612bf6602083018461455b565b828152604060208201526000612e9b604083018461455b565b6000806040838503121561531857600080fd5b61532183614a22565b9150602083015190509250929050565b600181815b8085111561538a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615370576153706149e0565b8085161561537d57918102915b93841c9390800290615336565b509250929050565b6000826153a157506001612bf9565b816153ae57506000612bf9565b81600181146153c457600281146153ce576153ea565b6001915050612bf9565b60ff8411156153df576153df6149e0565b50506001821b612bf9565b5060208310610133831016604e8410600b841016171561540d575081810a612bf9565b6154178383615331565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615449576154496149e0565b029392505050565b6000612bf68383615392565b600082615493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b5060405162005c3038038062005c3083398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516154f66200073a60003960008181610182015261022f0152600081816120e7015261228d01526000612bb30152600050506000612ee901526000613c5d01526000612fc3015260008181610c4701528181610d0801528181610dd30152612c7401526154f66000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e236600461439e565b610511565b3480156101f357600080fd5b50610207610202366004614512565b610617565b6040516102179493929190614631565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f3660046146b3565b6108f5565b3480156102a057600080fd5b506101c56102af3660046146ff565b610957565b3480156102c057600080fd5b506101c56102cf366004614718565b610b09565b3480156102e057600080fd5b506101c56102ef366004614744565b610d7c565b34801561030057600080fd5b5061031461030f366004614512565b61102a565b6040516102179796959493929190614785565b34801561033357600080fd5b506101c56103423660046146ff565b61178e565b34801561035357600080fd5b506101c561036236600461439e565b611824565b34801561037357600080fd5b506101c5611c9c565b34801561038857600080fd5b506101c56103973660046146ff565b611d99565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e23660046146b3565b611f4e565b6101c56103f53660046147d3565b611fa3565b34801561040657600080fd5b506101c561041536600461481b565b612365565b34801561042657600080fd5b506101c5610435366004614840565b612464565b34801561044657600080fd5b5061045a6104553660046146b3565b612545565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046146ff565b6126f0565b34801561049d57600080fd5b506101c56104ac3660046146b3565b61291d565b3480156104bd57600080fd5b506102076104cc3660046148ba565b6129d4565b3480156104dd57600080fd5b506101c56104ec36600461499c565b612a96565b3480156104fd57600080fd5b5061031461050c3660046146ff565b612aaa565b61051a82612ae6565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b9b565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906149c9565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e091906149e6565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614a31565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614a99565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ae6565b6000838152601d60205260409020610917828483614b7e565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614ce2565b60405180910390a2505050565b61096081612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612c0c565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c72565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614cf6565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c72565b128015610e835750600060255460ff166001811115610e8157610e816145c7565b145b15610eba576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614d11565b610f649190614a31565b905080821115610faa576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fcb73ffffffffffffffffffffffffffffffffffffffff85168484612d41565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061103e612b9b565b60006110498a612e1a565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a001511561140c5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611782915050565b606083015163ffffffff908116146114565750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611782915050565b8251156114955750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611782915050565b61149e84612ec5565b8094508198508299505050506114c38e858786604001518b8b888a61010001516130b7565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115255750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611782915050565b505060006115348d858e613427565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af91906149c9565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115ef91906149e6565b60006040518083038160008787f1925050503d806000811461162d576040519150601f19603f3d011682016040523d82523d6000602084013e611632565b606091505b50915091505a611642908b614a31565b9950816116c8576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116a75750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611782915050565b604090930151929a50600399505063ffffffff909116955061178292505050565b808060200190518101906116dc9190614a99565b909d509b508c6117165750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611782915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff1610156117705750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611782915050565b5050506040015163ffffffff16945050505b92959891949750929550565b611796613607565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561187c576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff811661190b576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a4b576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adf9190614d11565b816060015163ffffffff161115611b22576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b8d908290614a31565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611c109116846bffffffffffffffffffffffff8416612d41565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611da281612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611edc576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611f1e600283613658565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f5783612ae6565b6000838152601e60205260409020611f70828483614b7e565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614ce2565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120df576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b341561217b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461216f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61217834613664565b91505b818160c0015161218b9190614d2a565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205461221b91841690614d4f565b61010082015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604081209190915534900361228b576101008101516122869073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff8616613706565b61231b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b15801561230157600080fd5b505af1158015612315573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff1610806123a2575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123d9576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e282612ae6565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61246c613607565b6000828152600460205260409020546601000000000000900463ffffffff908116146124c4576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906125128282614d73565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124589190614dfa565b600080612550612b9b565b601454760100000000000000000000000000000000000000000000900460ff16156125a7576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126e393899089908190840183828082843760009201919091525061376a92505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461282c576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612889576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61292683612ae6565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612988576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526007602052604090206129a1828483614b7e565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614ce2565b600060606000806000634b56a42e60e01b8888886040516024016129fa93929190614e31565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a838982610617565b929c919b50995090975095505050505050565b612a9e613985565b612aa781613a06565b50565b600060606000806000806000612acf886040518060200160405280600081525061102a565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b43576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612aa7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612c0a576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612c188383613afb565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d329190614d11565b612d3c9190614ec7565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612e159084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b4a565b505050565b6000818160045b600f811015612ea7577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e5f57612e5f614ee7565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e9557506000949350505050565b80612e9f81614f16565b915050612e21565b5081600f1a6001811115612ebd57612ebd6145c7565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f769190614f68565b5094509092505050600081131580612f8d57508142105b80612fae5750828015612fae5750612fa58242614a31565b8463ffffffff16105b15612fbd576019549650612fc1565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561302c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130509190614f68565b509450909250505060008113158061306757508142105b806130885750828015613088575061307f8242614a31565b8463ffffffff16105b1561309757601a54955061309b565b8095505b86866130a68a613c56565b965096509650505050509193909250565b60008080808960018111156130ce576130ce6145c7565b036130dd575062016b48613132565b60018960018111156130f1576130f16145c7565b0361310057506201ccf0613132565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131459190614fb8565b6131539060ff166040614fd1565b601854613181906103a49074010000000000000000000000000000000000000000900463ffffffff16614d4f565b61318b9190614d4f565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190614fe8565b90925090508183613232836018614d4f565b61323c9190614fd1565b60808f015161324c906001614fb8565b61325b9060ff166115e0614fd1565b6132659190614d4f565b61326f9190614d4f565b6132799085614d4f565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190614d11565b8d6060015161ffff166133239190614fd1565b945050505060006133348b86613d47565b60008d815260046020526040902054909150610100900460ff16156133995760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006134038c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ec3565b6020810151815191925061341691614d2a565b9d9c50505050505050505050505050565b6060600083600181111561343d5761343d6145c7565b03613506576000848152600760205260409081902090517f6e04ff0d0000000000000000000000000000000000000000000000000000000091613482916024016150a7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050613600565b600183600181111561351a5761351a6145c7565b03613100576000828060200190518101906135359190615120565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161357a918491602401615230565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506136009050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612c188383614118565b60006bffffffffffffffffffffffff821115613702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137649085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d93565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137c7576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061383c9085906024016152fb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061390f908790879060040161530e565b60408051808303816000875af115801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615327565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b4257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612c1b565b506000612c1b565b6000613bac826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661420b9092919063ffffffff16565b805190915015612e155780806020019051810190613bca9190614cf6565b612e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cea9190614f68565b50935050925050600082131580613d0057508042105b80613d3057506000846040015162ffffff16118015613d305750613d248142614a31565b846040015162ffffff16105b15613d40575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e589190614f68565b50935050925050600082131580613e6e57508042105b80613e9e57506000866040015162ffffff16118015613e9e5750613e928142614a31565b866040015162ffffff16105b15613eb25760018301546060850152613eba565b606084018290525b50505092915050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613f119190614fd1565b90508361010001518015613f245750803a105b15613f2c57503a5b600060128311613f3d576001613f53565b613f48601284614a31565b613f5390600a615473565b9050600060128410613f66576001613f7c565b613f71846012614a31565b613f7c90600a615473565b905060008660a00151876040015188602001518960000151613f9e9190614d4f565b613fa89087614fd1565b613fb29190614d4f565b613fbc9190614fd1565b9050613fee828860e0015160600151613fd59190614fd1565b613fdf8584614fd1565b613fe9919061547f565b613664565b6bffffffffffffffffffffffff168652608087015161401190613fe9908361547f565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061404a9062ffffff16683635c9adc5dea00000614fd1565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61407d9190614fd1565b6140879190614d4f565b6140919190614fd1565b61409b9190614fd1565b6140a5919061547f565b6140af9190614d4f565b90506140d2848a60e00151606001516140c89190614fd1565b613fdf8784614fd1565b6bffffffffffffffffffffffff16602089015260808901516140f890613fe9908361547f565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b6000818152600183016020526040812054801561420157600061413c600183614a31565b855490915060009061415090600190614a31565b90508181146141b557600086600001828154811061417057614170614ee7565b906000526020600020015490508087600001848154811061419357614193614ee7565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141c6576141c66154ba565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c1b565b6000915050612c1b565b6060612ebd8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161423f91906149e6565b60006040518083038185875af1925050503d806000811461427c576040519150601f19603f3d011682016040523d82523d6000602084013e614281565b606091505b50915091506142928783838761429d565b979650505050505050565b6060831561433357825160000361432c5773ffffffffffffffffffffffffffffffffffffffff85163b61432c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612ebd565b612ebd83838151156143485781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906152fb565b73ffffffffffffffffffffffffffffffffffffffff81168114612aa757600080fd5b600080604083850312156143b157600080fd5b8235915060208301356143c38161437c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715614421576144216143ce565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561446e5761446e6143ce565b604052919050565b600067ffffffffffffffff821115614490576144906143ce565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126144cd57600080fd5b81356144e06144db82614476565b614427565b8181528460208386010111156144f557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561452557600080fd5b82359150602083013567ffffffffffffffff81111561454357600080fd5b61454f858286016144bc565b9150509250929050565b60005b8381101561457457818101518382015260200161455c565b50506000910152565b60008151808452614595816020860160208601614559565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061462d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061464c608083018661457d565b905061465b60408301856145f6565b82606083015295945050505050565b60008083601f84011261467c57600080fd5b50813567ffffffffffffffff81111561469457600080fd5b6020830191508360208285010111156146ac57600080fd5b9250929050565b6000806000604084860312156146c857600080fd5b83359250602084013567ffffffffffffffff8111156146e657600080fd5b6146f28682870161466a565b9497909650939450505050565b60006020828403121561471157600080fd5b5035919050565b6000806040838503121561472b57600080fd5b82356147368161437c565b946020939093013593505050565b60008060006060848603121561475957600080fd5b83356147648161437c565b925060208401356147748161437c565b929592945050506040919091013590565b871515815260e0602082015260006147a060e083018961457d565b90506147af60408301886145f6565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156147e657600080fd5b8235915060208301356bffffffffffffffffffffffff811681146143c357600080fd5b63ffffffff81168114612aa757600080fd5b6000806040838503121561482e57600080fd5b8235915060208301356143c381614809565b600080828403606081121561485457600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561488857600080fd5b506020830190509250929050565b600067ffffffffffffffff8211156148b0576148b06143ce565b5060051b60200190565b600080600080606085870312156148d057600080fd5b8435935060208086013567ffffffffffffffff808211156148f057600080fd5b818801915088601f83011261490457600080fd5b81356149126144db82614896565b81815260059190911b8301840190848101908b83111561493157600080fd5b8585015b838110156149695780358581111561494d5760008081fd5b61495b8e89838a01016144bc565b845250918601918601614935565b5097505050604088013592508083111561498257600080fd5b50506149908782880161466a565b95989497509550505050565b6000602082840312156149ae57600080fd5b81356136008161437c565b80516149c48161437c565b919050565b6000602082840312156149db57600080fd5b81516136008161437c565b600082516149f8818460208701614559565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612c1b57612c1b614a02565b805180151581146149c457600080fd5b600082601f830112614a6557600080fd5b8151614a736144db82614476565b818152846020838601011115614a8857600080fd5b612ebd826020830160208701614559565b60008060408385031215614aac57600080fd5b614ab583614a44565b9150602083015167ffffffffffffffff811115614ad157600080fd5b61454f85828601614a54565b600181811c90821680614af157607f821691505b602082108103614b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e1557600081815260208120601f850160051c81016020861015614b575750805b601f850160051c820191505b81811015614b7657828155600101614b63565b505050505050565b67ffffffffffffffff831115614b9657614b966143ce565b614baa83614ba48354614add565b83614b30565b6000601f841160018114614bfc5760008515614bc65750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614c92565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c4b5786850135825560209485019460019092019101614c2b565b5086821015614c86577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612ebd602083018486614c99565b600060208284031215614d0857600080fd5b612c1882614a44565b600060208284031215614d2357600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d4057613d40614a02565b80820180821115612c1b57612c1b614a02565b62ffffff81168114612aa757600080fd5b8135614d7e81614809565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614dbe81614d62565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614e0981614809565b63ffffffff1682526020830135614e1f81614d62565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614ea6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614e9486835161457d565b95509382019390820190600101614e5a565b505085840381870152505050614ebd818587614c99565b9695505050505050565b8181036000831280158383131683831282161715613d4057613d40614a02565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f4757614f47614a02565b5060010190565b805169ffffffffffffffffffff811681146149c457600080fd5b600080600080600060a08688031215614f8057600080fd5b614f8986614f4e565b9450602086015193506040860151925060608601519150614fac60808701614f4e565b90509295509295909350565b60ff8181168382160190811115612c1b57612c1b614a02565b8082028115828204841417612c1b57612c1b614a02565b60008060408385031215614ffb57600080fd5b505080516020909101519092909150565b6000815461501981614add565b808552602060018381168015615036576001811461506e5761509c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061509c565b866000528260002060005b858110156150945781548a8201860152908301908401615079565b890184019650505b505050505092915050565b602081526000612c18602083018461500c565b600082601f8301126150cb57600080fd5b815160206150db6144db83614896565b82815260059290921b840181019181810190868411156150fa57600080fd5b8286015b8481101561511557805183529183019183016150fe565b509695505050505050565b60006020828403121561513257600080fd5b815167ffffffffffffffff8082111561514a57600080fd5b90830190610100828603121561515f57600080fd5b6151676143fd565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261519f60a084016149b9565b60a082015260c0830151828111156151b657600080fd5b6151c2878286016150ba565b60c08301525060e0830151828111156151da57600080fd5b6151e687828601614a54565b60e08301525095945050505050565b600081518084526020808501945080840160005b8381101561522557815187529582019590820190600101615209565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506152a16101408401826151f5565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526152dd828261457d565b91505082810360208401526152f2818561500c565b95945050505050565b602081526000612c18602083018461457d565b828152604060208201526000612ebd604083018461457d565b6000806040838503121561533a57600080fd5b61534383614a44565b9150602083015190509250929050565b600181815b808511156153ac57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561539257615392614a02565b8085161561539f57918102915b93841c9390800290615358565b509250929050565b6000826153c357506001612c1b565b816153d057506000612c1b565b81600181146153e657600281146153f05761540c565b6001915050612c1b565b60ff84111561540157615401614a02565b50506001821b612c1b565b5060208310610133831016604e8410600b841016171561542f575081810a612c1b565b6154398383615353565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561546b5761546b614a02565b029392505050565b6000612c1883836153b4565b6000826154b5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } var AutomationRegistryLogicBABI = AutomationRegistryLogicBMetaData.ABI diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 9dbf6e87090..37a52ccd949 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -12,7 +12,7 @@ automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistra automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin e8ae5a25765092049f79eb8344db8e572bacb43c6c6e284b3d00f82667c248f7 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f -automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin 2d0f45d2087f6f3c8bfa0a16b26a1c8c1d5c64b89859478c609201535c96eeed +automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin f2bb8dc7fdb8b48ba0a0501e3c195676e73d0e56d94c9061edf12830ebbce495 automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin fa9159b9dd36e37209d9805d0fde82f1cba7d0e2674ecc5a7595d48eb40203c4 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 From fe2e8fd21d65c9faee6afa6668b8e12797b957ce Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Mon, 6 May 2024 02:09:02 +0300 Subject: [PATCH 17/35] VRF-1035: Add retrieval of VRF Wrapper Config in superscripts (#12977) --- core/scripts/vrfv2/testnet/main.go | 13 ++++++++++--- core/scripts/vrfv2/testnet/v2scripts/util.go | 15 +++++++++++---- core/scripts/vrfv2plus/testnet/main.go | 11 +++++++++-- .../vrfv2plus/testnet/v2plusscripts/util.go | 7 +++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go index 88f4d9e0f73..c0e62af781d 100644 --- a/core/scripts/vrfv2/testnet/main.go +++ b/core/scripts/vrfv2/testnet/main.go @@ -12,9 +12,6 @@ import ( "strings" "sync" - "github.com/smartcontractkit/chainlink/core/scripts/vrfv2/testnet/v2scripts" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner_test_consumer" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -22,6 +19,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/shopspring/decimal" + "github.com/smartcontractkit/chainlink/core/scripts/vrfv2/testnet/v2scripts" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner_test_consumer" + "github.com/jmoiron/sqlx" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" @@ -1294,6 +1294,13 @@ func main() { *wrapperPremiumPercentage, *keyHash, *maxNumWords) + case "wrapper-get-config": + cmd := flag.NewFlagSet("wrapper-get-config", flag.ExitOnError) + wrapperAddress := cmd.String("wrapper-address", "", "wrapper address") + helpers.ParseArgs(cmd, os.Args[2:], "wrapper-address") + wrapper, err := vrfv2_wrapper.NewVRFV2Wrapper(common.HexToAddress(*wrapperAddress), e.Ec) + helpers.PanicErr(err) + v2scripts.PrintWrapperConfig(wrapper) case "wrapper-get-fulfillment-tx-size": cmd := flag.NewFlagSet("wrapper-get-fulfillment-tx-size", flag.ExitOnError) wrapperAddress := cmd.String("wrapper-address", "", "address of the VRFV2Wrapper contract") diff --git a/core/scripts/vrfv2/testnet/v2scripts/util.go b/core/scripts/vrfv2/testnet/v2scripts/util.go index 325ced2ab21..2f6e7df23ec 100644 --- a/core/scripts/vrfv2/testnet/v2scripts/util.go +++ b/core/scripts/vrfv2/testnet/v2scripts/util.go @@ -7,14 +7,14 @@ import ( "fmt" "math/big" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" @@ -208,6 +208,13 @@ func WrapperConfigure( helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) } +func PrintWrapperConfig(wrapper *vrfv2_wrapper.VRFV2Wrapper) { + cfg, err := wrapper.GetConfig(nil) + helpers.PanicErr(err) + fmt.Printf("Wrapper config: %+v\n", cfg) + fmt.Printf("Wrapper Keyhash: %s\n", fmt.Sprintf("0x%x", cfg.KeyHash)) +} + func WrapperConsumerDeploy( e helpers.Environment, link, wrapper common.Address, diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index c2e6a710858..7b47a2f8529 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -11,6 +11,8 @@ import ( "os" "strings" + "github.com/ethereum/go-ethereum" + "github.com/smartcontractkit/chainlink/core/scripts/vrfv2plus/testnet/v2plusscripts" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_specific_util_helper" @@ -18,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -1234,7 +1235,13 @@ func main() { uint32(*stalenessSeconds), uint32(*fulfillmentFlatFeeNativePPM), uint32(*fulfillmentFlatFeeLinkDiscountPPM)) - + case "wrapper-get-config": + cmd := flag.NewFlagSet("wrapper-get-config", flag.ExitOnError) + wrapperAddress := cmd.String("wrapper-address", "", "wrapper address") + helpers.ParseArgs(cmd, os.Args[2:], "wrapper-address") + wrapper, err := vrfv2plus_wrapper.NewVRFV2PlusWrapper(common.HexToAddress(*wrapperAddress), e.Ec) + helpers.PanicErr(err) + v2plusscripts.PrintWrapperConfig(wrapper) case "wrapper-get-fulfillment-tx-size": cmd := flag.NewFlagSet("wrapper-get-fulfillment-tx-size", flag.ExitOnError) wrapperAddress := cmd.String("wrapper-address", "", "address of the VRFV2Wrapper contract") diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go index 6fbdc88b869..3d511605811 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go @@ -287,6 +287,13 @@ func WrapperConfigure( helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) } +func PrintWrapperConfig(wrapper *vrfv2plus_wrapper.VRFV2PlusWrapper) { + cfg, err := wrapper.GetConfig(nil) + helpers.PanicErr(err) + fmt.Printf("Wrapper config: %+v\n", cfg) + fmt.Printf("Wrapper Keyhash: %s\n", fmt.Sprintf("0x%x", cfg.KeyHash)) +} + func WrapperConsumerDeploy( e helpers.Environment, link, wrapper common.Address, From 36cc95f6256b5ba418a916de2c9dc9597508147a Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Mon, 6 May 2024 17:17:03 +0700 Subject: [PATCH 18/35] KSI-165: Implement update nodes (#13080) * implement update nodes * address PR feedback * regen go wrappers --- .changeset/modern-trainers-hear.md | 5 + contracts/.changeset/three-hotels-agree.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 46 ++++- .../CapabilityRegistry_AddNodesTest.t.sol | 47 ++++- .../CapabilityRegistry_UpdateNodesTest.t.sol | 195 ++++++++++++++++++ .../keystone_capability_registry.go | 149 ++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 444 insertions(+), 5 deletions(-) create mode 100644 .changeset/modern-trainers-hear.md create mode 100644 contracts/.changeset/three-hotels-agree.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol diff --git a/.changeset/modern-trainers-hear.md b/.changeset/modern-trainers-hear.md new file mode 100644 index 00000000000..08f7ab0988a --- /dev/null +++ b/.changeset/modern-trainers-hear.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Generate gethwrappers for capability registry changes diff --git a/contracts/.changeset/three-hotels-agree.md b/contracts/.changeset/three-hotels-agree.md new file mode 100644 index 00000000000..66ed4b2377e --- /dev/null +++ b/contracts/.changeset/three-hotels-agree.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Add function to update nodes in capability registry diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 9e0a67434fc..6ac4caedf50 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -106,6 +106,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param nodeOperatorId The ID of the node operator that manages this node event NodeAdded(bytes32 p2pId, uint256 nodeOperatorId); + /// @notice This event is emitted when a node is updated + /// @param p2pId The P2P ID of the node + /// @param nodeOperatorId The ID of the node operator that manages this node + /// @param signer The node's signer address + event NodeUpdated(bytes32 p2pId, uint256 nodeOperatorId, address signer); + + /// @notice This error is thrown when trying to set the node's + /// signer address to zero + error InvalidNodeSigner(); + /// @notice This error is thrown when trying add a capability that already /// exists. error CapabilityAlreadyExists(); @@ -236,12 +246,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { for (uint256 i; i < nodes.length; ++i) { Node memory node = nodes[i]; + bool isOwner = msg.sender == owner(); + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; - if (msg.sender != nodeOperator.admin) revert AccessForbidden(); + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(); bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; if (nodeExists || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + if (node.signer == address(0)) revert InvalidNodeSigner(); + if (node.supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); @@ -255,6 +269,36 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } } + /// @notice Updates nodes. The node admin can update the node's signer address + /// and reconfigure its supported capabilities + /// @param nodes The nodes to update + function updateNodes(Node[] calldata nodes) external { + for (uint256 i; i < nodes.length; ++i) { + Node memory node = nodes[i]; + + bool isOwner = msg.sender == owner(); + + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(); + + bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; + if (!nodeExists) revert InvalidNodeP2PId(node.p2pId); + + if (node.signer == address(0)) revert InvalidNodeSigner(); + + if (node.supportedHashedCapabilityIds.length == 0) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); + + for (uint256 j; j < node.supportedHashedCapabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(node.supportedHashedCapabilityIds[j])) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); + } + + s_nodes[node.p2pId] = node; + emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); + } + } + /// @notice Gets a node's data /// @param p2pId The P2P ID of the node to query for /// @return Node The node data diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol index e179cc5cea6..9174e4ed0d3 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -18,7 +18,7 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); } - function test_RevertWhen_CalledByNonNodeOperatorAdmin() public { + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { changePrank(STRANGER); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); @@ -36,6 +36,24 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { s_capabilityRegistry.addNodes(nodes); } + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: address(0), + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); + s_capabilityRegistry.addNodes(nodes); + } + function test_RevertWhen_AddingDuplicateP2PId() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); @@ -133,4 +151,31 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); } + + function test_OwnerCanAddNodes() public { + changePrank(ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID); + s_capabilityRegistry.addNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.supportedHashedCapabilityIds.length, 2); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol new file mode 100644 index 00000000000..7ccbd14dbf2 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_UpdateNodesTest is BaseTest { + event NodeUpdated(bytes32 p2pId, uint256 nodeOperatorId, address signer); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + bytes32 private constant INVALID_P2P_ID = bytes32("fake-p2p"); + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: INVALID_P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, INVALID_P2P_ID)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: address(0), + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](0); + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_UpdatesNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + s_capabilityRegistry.updateNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + assertEq(node.supportedHashedCapabilityIds.length, 1); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + } + + function test_OwnerCanUpdateNodes() public { + changePrank(ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + s_capabilityRegistry.updateNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + assertEq(node.supportedHashedCapabilityIds.length, 1); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 8ea5e29d99c..9080fbd7807 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -50,8 +50,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf63431461019457806336b402fb146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6125e680620001606000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806365c14dc7116100b2578063ae3c241c11610081578063c2d483a111610066578063c2d483a1146102d3578063ddbe4f82146102e6578063f2fde38b146102fb57600080fd5b8063ae3c241c146102ad578063b38e51f6146102c057600080fd5b806365c14dc71461023d57806379ba50971461025d5780638da5cb5b146102655780639cb7c5f41461028d57600080fd5b80631cdf6343116100ee5780631cdf6343146101af57806336b402fb146101c2578063398f37731461020a57806350c946fe1461021d57600080fd5b80630c5801e314610120578063117392ce146101355780631257001114610148578063181f5a7714610170575b600080fd5b61013361012e366004611b8d565b61030e565b005b610133610143366004611bf9565b61061f565b61015b610156366004611c11565b61086a565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101679190611c8e565b6101336101bd366004611ca1565b61087d565b6101fc6101d0366004611ce3565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610167565b610133610218366004611ca1565b610940565b61023061022b366004611c11565b610ad9565b6040516101679190611d05565b61025061024b366004611c11565b610ba1565b6040516101679190611d8b565b610133610c7e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610167565b6102a061029b366004611c11565b610d7b565b6040516101679190611e6d565b6101336102bb366004611c11565b610e25565b6101336102ce366004611ca1565b610ef0565b6101336102e1366004611ca1565b61130c565b6102ee6116ed565b6040516101679190611e7b565b610133610309366004611eeb565b611832565b828114610356576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561061757600086868381811061038e5761038e611f08565b90506020020135905060008585848181106103ab576103ab611f08565b90506020028101906103bd9190611f37565b6103c69061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff16610417576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061045457503373ffffffffffffffffffffffffffffffffffffffff851614155b1561048b576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061053d57506020808201516040516104d19201611c8e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600086815260078352929092209192610524926001019101612158565b6040516020818303038152906040528051906020012014155b15610604578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906105aa9082612247565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105fb929190612361565b60405180910390a25b505080610610906123a9565b9050610372565b505050505050565b610627611846565b60408051823560208281019190915280840135828401528251808303840181526060909201909252805191012061065f6003826118c9565b15610696576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106a86080840160608501611eeb565b73ffffffffffffffffffffffffffffffffffffffff1614610813576106d36080830160608401611eeb565b73ffffffffffffffffffffffffffffffffffffffff163b15806107b357506107016080830160608401611eeb565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b191906123e1565b155b15610813576107c86080830160608401611eeb565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161034d565b61081e6003826118e4565b50600081815260026020526040902082906108398282612403565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b60006108776005836118c9565b92915050565b610885611846565b60005b8181101561093b5760008383838181106108a4576108a4611f08565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108f56001830182611aa7565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610934816123a9565b9050610888565b505050565b610948611846565b60005b8181101561093b57600083838381811061096757610967611f08565b90506020028101906109799190611f37565b6109829061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff166109d3576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a569082612247565b50905050600960008154610a69906123a9565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610abe91859190612361565b60405180910390a2505080610ad2906123a9565b905061094b565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b9157602002820191906000526020600020905b815481526020019060010190808311610b7d575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bfe9061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2a9061210b565b8015610b915780601f10610c4c57610100808354040283529160200191610b91565b820191906000526020600020905b815481529060010190602001808311610c5a57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161034d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610de457610de4611dce565b6001811115610df557610df5611dce565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610e2d611846565b610e386003826118c9565b610e71576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610e7c6005826118c9565b15610eb6576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610ec16005826118e4565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561093b576000838383818110610f0f57610f0f611f08565b9050602002810190610f219190612485565b610f2a906124b9565b90506000610f4d60005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff90811683526001820180549690911633149650939491939092840191610fa49061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610fd09061210b565b801561101d5780601f10610ff25761010080835404028352916020019161101d565b820191906000526020600020905b81548152906001019060200180831161100057829003601f168201915b50505050508152505090508115801561104d5750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611084576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808401516000908152600890915260409020600301541515806110dd5783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff1661112e576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360600151516000036111735783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611200576111b48560600151828151811061119c5761119c611f08565b602002602001015160036118c990919063ffffffff16565b6111f05784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b6111f9816123a9565b9050611176565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611285926003850192910190611ae1565b509050507f6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e8460200151856000015186604001516040516112ef93929190928352602083019190915273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b60405180910390a15050505080611305906123a9565b9050610ef3565b60005b8181101561093b57600083838381811061132b5761132b611f08565b905060200281019061133d9190612485565b611346906124b9565b9050600061136960005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff908116835260018201805496909116331496509394919390928401916113c09061210b565b80601f01602080910402602001604051908101604052809291908181526020018280546113ec9061210b565b80156114395780601f1061140e57610100808354040283529160200191611439565b820191906000526020600020905b81548152906001019060200180831161141c57829003601f168201915b5050505050815250509050811580156114695750805173ffffffffffffffffffffffffffffffffffffffff163314155b156114a0576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602080840151600090815260089091526040902060030154151580806114c857506020840151155b156115075783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff16611558576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83606001515160000361159d5783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611612576115c68560600151828151811061119c5761119c611f08565b6116025784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b61160b816123a9565b90506115a0565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611697926003850192910190611ae1565b505050602084810151855160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a150505050806116e6906123a9565b905061130f565b606060006116fb60036118f0565b9050600061170960056118fd565b825161171591906125c6565b67ffffffffffffffff81111561172d5761172d611f75565b60405190808252806020026020018201604052801561179d57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161174b5790505b5090506000805b83518110156118295760008482815181106117c1576117c1611f08565b602002602001015190506117df8160056118c990919063ffffffff16565b611818576117ec81610d7b565b8484815181106117fe576117fe611f08565b60200260200101819052508280611814906123a9565b9350505b50611822816123a9565b90506117a4565b50909392505050565b61183a611846565b61184381611907565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161034d565b565b600081815260018301602052604081205415155b9392505050565b60006118dd83836119fc565b606060006118dd83611a4b565b6000610877825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161034d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054611a4357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610877565b506000610877565b606081600001805480602002602001604051908101604052809291908181526020018280548015611a9b57602002820191906000526020600020905b815481526020019060010190808311611a87575b50505050509050919050565b508054611ab39061210b565b6000825580601f10611ac3575050565b601f0160209004906000526020600020908101906118439190611b2c565b828054828255906000526020600020908101928215611b1c579160200282015b82811115611b1c578251825591602001919060010190611b01565b50611b28929150611b2c565b5090565b5b80821115611b285760008155600101611b2d565b60008083601f840112611b5357600080fd5b50813567ffffffffffffffff811115611b6b57600080fd5b6020830191508360208260051b8501011115611b8657600080fd5b9250929050565b60008060008060408587031215611ba357600080fd5b843567ffffffffffffffff80821115611bbb57600080fd5b611bc788838901611b41565b90965094506020870135915080821115611be057600080fd5b50611bed87828801611b41565b95989497509550505050565b600060808284031215611c0b57600080fd5b50919050565b600060208284031215611c2357600080fd5b5035919050565b6000815180845260005b81811015611c5057602081850181015186830182015201611c34565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006118dd6020830184611c2a565b60008060208385031215611cb457600080fd5b823567ffffffffffffffff811115611ccb57600080fd5b611cd785828601611b41565b90969095509350505050565b60008060408385031215611cf657600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b80831015611d805783518252928401926001929092019190840190611d60565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152611dc66060840182611c2a565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110611e47577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108778284611dfd565b6020808252825182820181905260009190848201906040850190845b81811015611ebd57611eaa838551611dfd565b9284019260809290920191600101611e97565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461184357600080fd5b600060208284031215611efd57600080fd5b81356118dd81611ec9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611f6b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fc757611fc7611f75565b60405290565b6040516080810167ffffffffffffffff81118282101715611fc757611fc7611f75565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203757612037611f75565b604052919050565b60006040823603121561205157600080fd5b612059611fa4565b823561206481611ec9565b815260208381013567ffffffffffffffff8082111561208257600080fd5b9085019036601f83011261209557600080fd5b8135818111156120a7576120a7611f75565b6120d7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ff0565b915080825236848285010111156120ed57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061211f57607f821691505b602082108103611c0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060208083526000845461216c8161210b565b8084870152604060018084166000811461218d57600181146121c5576121f3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506121f3565b896000528660002060005b858110156121eb5781548b82018601529083019088016121d0565b8a0184019650505b509398975050505050505050565b601f82111561093b57600081815260208120601f850160051c810160208610156122285750805b601f850160051c820191505b8181101561061757828155600101612234565b815167ffffffffffffffff81111561226157612261611f75565b6122758161226f845461210b565b84612201565b602080601f8311600181146122c857600084156122925750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610617565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612315578886015182559484019460019091019084016122f6565b508582101561235157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000611dc66040830184611c2a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123da576123da61237a565b5060010190565b6000602082840312156123f357600080fd5b815180151581146118dd57600080fd5b81358155602082013560018201556002810160408301356002811061242757600080fd5b8154606085013561243781611ec9565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611f6b57600080fd5b6000608082360312156124cb57600080fd5b6124d3611fcd565b823581526020808401358183015260408401356124ef81611ec9565b6040830152606084013567ffffffffffffffff8082111561250f57600080fd5b9085019036601f83011261252257600080fd5b81358181111561253457612534611f75565b8060051b9150612545848301611ff0565b818152918301840191848101903684111561255f57600080fd5b938501935b8385101561257d57843582529385019390850190612564565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611ebd578351835292840192918401916001016125aa565b818103818111156108775761087761237a56fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -462,6 +462,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodeOperat return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "updateNodes", nodes) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) UpdateNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + type CapabilityRegistryCapabilityAddedIterator struct { Event *CapabilityRegistryCapabilityAdded @@ -1209,6 +1221,125 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorUpdated( return event, nil } +type CapabilityRegistryNodeUpdatedIterator struct { + Event *CapabilityRegistryNodeUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeUpdated struct { + P2pId [32]byte + NodeOperatorId *big.Int + Signer common.Address + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts) (*CapabilityRegistryNodeUpdatedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeUpdated") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeUpdatedIterator{contract: _CapabilityRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) { + event := new(CapabilityRegistryNodeUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -1495,6 +1626,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseNodeOperatorRemoved(log) case _CapabilityRegistry.abi.Events["NodeOperatorUpdated"].ID: return _CapabilityRegistry.ParseNodeOperatorUpdated(log) + case _CapabilityRegistry.abi.Events["NodeUpdated"].ID: + return _CapabilityRegistry.ParseNodeUpdated(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -1529,6 +1662,10 @@ func (CapabilityRegistryNodeOperatorUpdated) Topic() common.Hash { return common.HexToHash("0x14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a") } +func (CapabilityRegistryNodeUpdated) Topic() common.Hash { + return common.HexToHash("0x6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1574,6 +1711,8 @@ type CapabilityRegistryInterface interface { UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) + FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) @@ -1610,6 +1749,12 @@ type CapabilityRegistryInterface interface { ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) + FilterNodeUpdated(opts *bind.FilterOpts) (*CapabilityRegistryNodeUpdatedIterator, error) + + WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated) (event.Subscription, error) + + ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 182c8da3f7e..e2bb9865809 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin aeb366351d69f320c610419a3e09a991bd6ea75690778835eb8f6421d1277f44 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 98d53a1997053a3037827ffd170c12f49d2005a5c266a1ea9eb69bb51e862f37 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 09f8c7fcd63bd4cc11a193b49f808f42e3d1f37a Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 6 May 2024 18:40:29 +0200 Subject: [PATCH 19/35] [TT-849] Move TestConfig's common parts to CTF (#13046) * use latest Seth * move test config to CTF * use latest CTF that fixes eth2 genesis generation * use latest Seth * use tagged CTF version --- integration-tests/actions/private_network.go | 8 ++--- .../actions/vrf/vrfv2/setup_steps.go | 2 +- .../actions/vrf/vrfv2plus/setup_steps.go | 2 +- .../docker/cmd/internal/commands.go | 2 +- integration-tests/docker/test_env/test_env.go | 31 ++++++++++--------- .../docker/test_env/test_env_builder.go | 14 ++++----- .../docker/test_env/test_env_config.go | 12 +++---- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +-- .../load/functions/onchain_monitoring.go | 4 +-- integration-tests/load/functions/setup.go | 4 +-- integration-tests/load/go.mod | 4 +-- integration-tests/load/go.sum | 8 ++--- .../migration/upgrade_version_test.go | 2 +- integration-tests/smoke/automation_test.go | 4 +-- integration-tests/smoke/cron_test.go | 4 +-- integration-tests/smoke/flux_test.go | 2 +- integration-tests/smoke/forwarder_ocr_test.go | 2 +- .../smoke/forwarders_ocr2_test.go | 2 +- integration-tests/smoke/keeper_test.go | 2 +- integration-tests/smoke/ocr2_test.go | 2 +- integration-tests/smoke/ocr_test.go | 2 +- integration-tests/smoke/runlog_test.go | 2 +- integration-tests/smoke/vrf_test.go | 2 +- integration-tests/testconfig/testconfig.go | 31 ++----------------- .../testconfig/testconfig_test.go | 16 +++++----- integration-tests/types/testconfigs.go | 19 ++++++------ .../universal/log_poller/helpers.go | 2 +- 28 files changed, 84 insertions(+), 107 deletions(-) diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index 01a084b66d8..70239a60060 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -3,17 +3,17 @@ package actions import ( "github.com/rs/zerolog" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) -func EthereumNetworkConfigFromConfig(l zerolog.Logger, config tc.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { +func EthereumNetworkConfigFromConfig(l zerolog.Logger, config ctf_config.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { if config.GetPrivateEthereumNetworkConfig() == nil { l.Warn().Msg("No TOML private ethereum network config found, will use old geth") ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() network, err = ethBuilder. - WithEthereumVersion(ctf_test_env.EthereumVersion_Eth1). - WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth). + WithEthereumVersion(ctf_config.EthereumVersion_Eth1). + WithExecutionLayer(ctf_config.ExecutionLayer_Geth). Build() return diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index bd41fb33e4e..ca85bdb5f19 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -359,7 +359,7 @@ func SetupVRFV2ForNewEnv( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&testConfig). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup(cleanupFn). diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 0b7be600cc2..ed81935fa2b 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -402,7 +402,7 @@ func SetupVRFV2PlusForNewEnv( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&testConfig). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup(cleanupFn). diff --git a/integration-tests/docker/cmd/internal/commands.go b/integration-tests/docker/cmd/internal/commands.go index 074cfb8083d..e05e5d89fac 100644 --- a/integration-tests/docker/cmd/internal/commands.go +++ b/integration-tests/docker/cmd/internal/commands.go @@ -43,7 +43,7 @@ var StartNodesCmd = &cobra.Command{ _, err = test_env.NewCLTestEnvBuilder(). WithTestConfig(&config). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(nodeCount). WithoutCleanup(). diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index fc0ba355556..fd1555ec055 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -18,6 +18,7 @@ import ( tc "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" d "github.com/smartcontractkit/chainlink/integration-tests/docker" - core_testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -40,7 +40,7 @@ type CLClusterTestEnv struct { Cfg *TestEnvConfig DockerNetwork *tc.DockerNetwork LogStream *logstream.LogStream - TestConfig core_testconfig.GlobalTestConfig + TestConfig ctf_config.GlobalTestConfig /* components */ ClCluster *ClCluster @@ -49,7 +49,7 @@ type CLClusterTestEnv struct { sethClients map[int64]*seth.Client ContractDeployer contracts.ContractDeployer ContractLoader contracts.ContractLoader - PrivateEthereumConfigs []*test_env.EthereumNetwork // new approach to private chains, supporting eth1 and eth2 + PrivateEthereumConfigs []*ctf_config.EthereumNetworkConfig EVMNetworks []*blockchain.EVMNetwork rpcProviders map[int64]*test_env.RpcProvider l zerolog.Logger @@ -95,18 +95,11 @@ func (te *CLClusterTestEnv) ParallelTransactions(enabled bool) { } } -func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *test_env.EthereumNetwork) (blockchain.EVMNetwork, test_env.RpcProvider, error) { +func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetworkConfig) (blockchain.EVMNetwork, test_env.RpcProvider, error) { // if environment is being restored from a previous state, use the existing config // this might fail terribly if temporary folders with chain data on the host machine were removed - if te.Cfg != nil && te.Cfg.EthereumNetwork != nil { - builder := test_env.NewEthereumNetworkBuilder() - c, err := builder.WithExistingConfig(*te.Cfg.EthereumNetwork). - WithTest(te.t). - Build() - if err != nil { - return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err - } - cfg = &c + if te.Cfg != nil && te.Cfg.EthereumNetworkConfig != nil { + cfg = te.Cfg.EthereumNetworkConfig } te.l.Info(). @@ -115,7 +108,15 @@ func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *test_env.EthereumNetwork) Str("Custom Docker Images", fmt.Sprintf("%v", cfg.CustomDockerImages)). Msg("Starting Ethereum network") - n, rpc, err := cfg.Start() + builder := test_env.NewEthereumNetworkBuilder() + c, err := builder.WithExistingConfig(*cfg). + WithTest(te.t). + Build() + if err != nil { + return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err + } + + n, rpc, err := c.Start() if err != nil { return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err @@ -129,7 +130,7 @@ func (te *CLClusterTestEnv) StartMockAdapter() error { } // pass config here -func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig core_testconfig.GlobalTestConfig, opts ...ClNodeOption) error { +func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig ctf_config.GlobalTestConfig, opts ...ClNodeOption) error { if te.Cfg != nil && te.Cfg.ClCluster != nil { te.ClCluster = te.Cfg.ClCluster } else { diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index c2aa07c8fa9..c8b4ac8e734 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/seth" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" @@ -23,7 +24,6 @@ import ( actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/integration-tests/utils" ) @@ -56,8 +56,8 @@ type CLTestEnvBuilder struct { cleanUpCustomFn func() chainOptionsFn []ChainOption evmClientNetworkOption []EVMClientNetworkOption - privateEthereumNetworks []*test_env.EthereumNetwork - testConfig tc.GlobalTestConfig + privateEthereumNetworks []*ctf_config.EthereumNetworkConfig + testConfig ctf_config.GlobalTestConfig /* funding */ ETHFunds *big.Float @@ -120,7 +120,7 @@ func (b *CLTestEnvBuilder) WithCLNodes(clNodesCount int) *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithTestConfig(cfg tc.GlobalTestConfig) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithTestConfig(cfg ctf_config.GlobalTestConfig) *CLTestEnvBuilder { b.testConfig = cfg return b } @@ -146,12 +146,12 @@ func (b *CLTestEnvBuilder) WithSeth() *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en test_env.EthereumNetwork) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = append(b.privateEthereumNetworks, &en) return b } -func (b *CLTestEnvBuilder) WithPrivateEthereumNetworks(ens []*test_env.EthereumNetwork) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithPrivateEthereumNetworks(ens []*ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = ens return b } @@ -300,7 +300,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if err != nil { return nil, err } - b.privateEthereumNetworks[i] = &netWithLs + b.privateEthereumNetworks[i] = &netWithLs.EthereumNetworkConfig } } diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go index 0902deb0c2d..9aefa9615c9 100644 --- a/integration-tests/docker/test_env/test_env_config.go +++ b/integration-tests/docker/test_env/test_env_config.go @@ -3,16 +3,16 @@ package test_env import ( "encoding/json" - cte "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" env "github.com/smartcontractkit/chainlink/integration-tests/types/envcommon" ) type TestEnvConfig struct { - Networks []string `json:"networks"` - Geth GethConfig `json:"geth"` - MockAdapter MockAdapterConfig `json:"mock_adapter"` - ClCluster *ClCluster `json:"clCluster"` - EthereumNetwork *cte.EthereumNetwork `json:"private_ethereum_config"` + Networks []string `json:"networks"` + Geth GethConfig `json:"geth"` + MockAdapter MockAdapterConfig `json:"mock_adapter"` + ClCluster *ClCluster `json:"clCluster"` + EthereumNetworkConfig *ctf_config.EthereumNetworkConfig `json:"private_ethereum_config"` } type MockAdapterConfig struct { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 3d76a656be5..babf82a7d96 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -26,7 +26,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.7 + github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 61fef05bbad..95f686a6d28 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1529,8 +1529,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8 h1:EaxNwB/16wpISzaUn2WJ4bE3TawD3joEekIlQuWNRGo= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= 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= diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go index 12a10ce0042..31ca8752dd3 100644 --- a/integration-tests/load/functions/onchain_monitoring.go +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" ) /* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ @@ -25,7 +25,7 @@ type LoadStats struct { Empty uint32 } -func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string, config tc.GlobalTestConfig) { +func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string, config ctf_config.GlobalTestConfig) { go func() { updatedLabels := make(map[string]string) for k, v := range labels { diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 4e353ff93a9..190dbbd8692 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -16,8 +16,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types" "github.com/smartcontractkit/chainlink/integration-tests/utils" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -50,7 +50,7 @@ type S4SecretsCfg struct { S4SetPayload string } -func SetupLocalLoadTestEnv(globalConfig tc.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { +func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] readSethCfg := globalConfig.GetSethConfig() sethCfg, err := utils.MergeSethAndEvmNetworkConfigs(selectedNetwork, *readSethCfg) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c8fde175cab..c179a3619f7 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,11 +17,11 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.7 + github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c - github.com/smartcontractkit/seth v0.1.6 + github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.6 github.com/stretchr/testify v1.9.0 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 46646e6b289..2c31f0fa335 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1512,8 +1512,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8 h1:EaxNwB/16wpISzaUn2WJ4bE3TawD3joEekIlQuWNRGo= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea h1:ZdLmNAfKRjH8AYUvjiiDGUgiWQfq/7iNpxyTkvjx/ko= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea/go.mod h1:gCKC9w6XpNk6jm+XIk2psrkkfxhi421N9NSiFceXW88= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= @@ -1524,8 +1524,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= 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 v0.1.6 h1:exU96KiKM/gxvp7OR8KkOXnTgbtFNepdhMBvyobFKCw= -github.com/smartcontractkit/seth v0.1.6/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec h1:BT1loU6TT2YqMenD7XE+aw7IeeTiC25+r1TLKAySVIg= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index 47761c09e50..f89644eb815 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -30,7 +30,7 @@ func TestVersionUpgrade(t *testing.T) { WithTestConfig(&config). WithTestInstance(t). WithStandardCleanup(). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithStandardCleanup(). WithSeth(). diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 73a7749c4e1..81d18139122 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -1160,7 +1160,7 @@ func setupAutomationTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(automationTestConfig). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). @@ -1200,7 +1200,7 @@ func setupAutomationTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(automationTestConfig). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 218727b7d66..e281824f0bb 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -32,7 +32,7 @@ func TestCronBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). @@ -88,7 +88,7 @@ func TestCronJobReplacement(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 023dd9dae89..4165e9b79b7 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -39,7 +39,7 @@ func TestFluxBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(3). WithStandardCleanup(). diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 5a8e51f871f..1ff132f09ab 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -35,7 +35,7 @@ func TestForwarderOCRBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithForwarders(). WithCLNodes(6). diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index ee86e8cc4b6..d3aa9e85ce6 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -38,7 +38,7 @@ func TestForwarderOCR2Basic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 7f2183faeac..fbfe4c73c89 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1166,7 +1166,7 @@ func setupKeeperTest(l zerolog.Logger, t *testing.T, config *tc.TestConfig) ( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(5). WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(.5)). diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index d4f7d1e7ffd..d2df0c858c0 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -138,7 +138,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 29e633beb15..bef08493962 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -91,7 +91,7 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). WithFunding(big.NewFloat(.5)). diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index d255fe07235..b01c5a019b1 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -36,7 +36,7 @@ func TestRunLogBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 3a28c14be00..ed8f756396f 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -192,7 +192,7 @@ func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestE env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 30a795e1881..fbaf80a2c88 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -19,8 +19,6 @@ import ( "github.com/smartcontractkit/seth" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" @@ -35,15 +33,6 @@ import ( vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" ) -type GlobalTestConfig interface { - GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig - GetLoggingConfig() *ctf_config.LoggingConfig - GetNetworkConfig() *ctf_config.NetworkConfig - GetPrivateEthereumNetworkConfig() *test_env.EthereumNetwork - GetPyroscopeConfig() *ctf_config.PyroscopeConfig - SethConfig -} - type UpgradeableChainlinkTestConfig interface { GetChainlinkUpgradeImageConfig() *ctf_config.ChainlinkImageConfig } @@ -80,24 +69,8 @@ type Ocr2TestConfig interface { GetOCR2Config() *ocr2_config.Config } -type NamedConfiguration interface { - GetConfigurationName() string -} - -type SethConfig interface { - GetSethConfig() *seth.Config -} - type TestConfig struct { - ChainlinkImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkImage"` - ChainlinkUpgradeImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkUpgradeImage"` - Logging *ctf_config.LoggingConfig `toml:"Logging"` - Network *ctf_config.NetworkConfig `toml:"Network"` - Pyroscope *ctf_config.PyroscopeConfig `toml:"Pyroscope"` - PrivateEthereumNetwork *ctf_test_env.EthereumNetwork `toml:"PrivateEthereumNetwork"` - WaspConfig *ctf_config.WaspAutoBuildConfig `toml:"WaspAutoBuild"` - - Seth *seth.Config `toml:"Seth"` + ctf_config.TestConfig Common *Common `toml:"Common"` Automation *a_config.Config `toml:"Automation"` @@ -182,7 +155,7 @@ func (c TestConfig) GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig { return c.ChainlinkImage } -func (c TestConfig) GetPrivateEthereumNetworkConfig() *ctf_test_env.EthereumNetwork { +func (c TestConfig) GetPrivateEthereumNetworkConfig() *ctf_config.EthereumNetworkConfig { return c.PrivateEthereumNetwork } diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go index 4a9dbdaade3..fd5230dac2d 100644 --- a/integration-tests/testconfig/testconfig_test.go +++ b/integration-tests/testconfig/testconfig_test.go @@ -57,13 +57,15 @@ func TestBase64ConfigRead(t *testing.T) { }, }, }, - Network: &ctf_config.NetworkConfig{ - SelectedNetworks: []string{"OPTIMISM_GOERLI"}, - RpcHttpUrls: map[string][]string{ - "OPTIMISM_GOERLI": {"http://localhost:8545"}, - }, - WalletKeys: map[string][]string{ - "OPTIMISM_GOERLI": {"0x3333333333333333333333333333333333333333"}, + TestConfig: ctf_config.TestConfig{ + Network: &ctf_config.NetworkConfig{ + SelectedNetworks: []string{"OPTIMISM_GOERLI"}, + RpcHttpUrls: map[string][]string{ + "OPTIMISM_GOERLI": {"http://localhost:8545"}, + }, + WalletKeys: map[string][]string{ + "OPTIMISM_GOERLI": {"0x3333333333333333333333333333333333333333"}, + }, }, }, } diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index cfebf0a3c7a..58eb1a7c8cf 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -1,52 +1,53 @@ package types import ( + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) type VRFv2TestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.VRFv2TestConfig } type VRFv2PlusTestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.VRFv2PlusTestConfig } type FunctionsTestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.FunctionsTestConfig } type AutomationTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.UpgradeableChainlinkTestConfig tc.AutomationTestConfig } type KeeperBenchmarkTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.KeeperTestConfig - tc.NamedConfiguration + ctf_config.NamedConfiguration testreporters.GrafanaURLProvider } type OcrTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.OcrTestConfig - tc.SethConfig + ctf_config.SethConfig } type Ocr2TestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.Ocr2TestConfig } diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 4759818d11c..fe3732cb47b 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -1131,7 +1131,7 @@ func SetupLogPollerTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestConfig(testConfig). WithTestInstance(t). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(chainlinkNodeFunding)). From 0955d4657113e3e069429391783bd15bf92040b3 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 6 May 2024 17:49:09 +0100 Subject: [PATCH 20/35] [KS-90] Add database-backed store (#13045) * [KS-90] Add database-backed store * [KS-90] Add database-backed store --- core/services/chainlink/application.go | 4 + core/services/workflows/delegate.go | 7 +- core/services/workflows/engine.go | 236 +++++++---- core/services/workflows/engine_test.go | 258 +++++++++--- core/services/workflows/models.go | 3 +- core/services/workflows/state.go | 81 ++-- core/services/workflows/state_test.go | 109 ++--- core/services/workflows/store.go | 70 ---- core/services/workflows/store/models.go | 41 ++ core/services/workflows/store/store.go | 16 + core/services/workflows/store/store_db.go | 382 ++++++++++++++++++ .../services/workflows/store/store_db_test.go | 215 ++++++++++ core/services/workflows/store/store_memory.go | 86 ++++ .../migrations/0235_add_workflow_models.sql | 47 +++ 14 files changed, 1249 insertions(+), 306 deletions(-) delete mode 100644 core/services/workflows/store.go create mode 100644 core/services/workflows/store/models.go create mode 100644 core/services/workflows/store/store.go create mode 100644 core/services/workflows/store/store_db.go create mode 100644 core/services/workflows/store/store_db_test.go create mode 100644 core/services/workflows/store/store_memory.go create mode 100644 core/store/migrate/migrations/0235_add_workflow_models.sql diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index ae3db2e7a73..ef4b0d870dd 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/grafana/pyroscope-go" + "github.com/jonboulle/clockwork" "github.com/pkg/errors" "go.uber.org/multierr" "go.uber.org/zap/zapcore" @@ -63,6 +64,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" + workflowstore "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth" "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth" @@ -319,6 +321,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobORM = job.NewORM(opts.DS, pipelineORM, bridgeORM, keyStore, globalLogger) txmORM = txmgr.NewTxStore(opts.DS, globalLogger) streamRegistry = streams.NewRegistry(globalLogger, pipelineRunner) + workflowORM = workflowstore.NewDBStore(opts.DS, clockwork.NewRealClock()) ) for _, chain := range legacyEVMChains.Slice() { @@ -388,6 +391,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, registry, legacyEVMChains, + workflowORM, func() *p2ptypes.PeerID { if externalPeerWrapper == nil { return nil diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index 8dc440da477..9db802f9a2f 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) type Delegate struct { @@ -22,6 +23,7 @@ type Delegate struct { logger logger.Logger legacyEVMChains legacyevm.LegacyChainContainer peerID func() *p2ptypes.PeerID + store store.Store } var _ job.Delegate = (*Delegate)(nil) @@ -58,6 +60,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser Registry: d.registry, DONInfo: dinfo, PeerID: d.peerID, + Store: d.store, } engine, err := NewEngine(cfg) if err != nil { @@ -103,8 +106,8 @@ func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { }, nil } -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, peerID func() *p2ptypes.PeerID) *Delegate { - return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, peerID: peerID} +func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, store store.Store, peerID func() *p2ptypes.PeerID) *Delegate { + return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, store: store, peerID: peerID} } func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index e405102e123..292ad9c6468 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -8,18 +8,20 @@ import ( "sync" "time" + "github.com/jonboulle/clockwork" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) const ( // NOTE: max 32 bytes per ID - consider enforcing exactly 32 bytes? - mockedTriggerID = "cccccccccc0000000000000000000000" - mockedWorkflowID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + mockedTriggerID = "cccccccccc0000000000000000000000" ) type donInfo struct { @@ -30,18 +32,19 @@ type donInfo struct { // Engine handles the lifecycle of a single workflow and its executions. type Engine struct { services.StateMachine - logger logger.Logger - registry core.CapabilitiesRegistry - workflow *workflow - donInfo donInfo - executionStates *inMemoryStore - pendingStepRequests chan stepRequest - triggerEvents chan capabilities.CapabilityResponse - newWorkerCh chan struct{} - stepUpdateCh chan stepState - wg sync.WaitGroup - stopCh services.StopChan - newWorkerTimeout time.Duration + logger logger.Logger + registry core.CapabilitiesRegistry + workflow *workflow + donInfo donInfo + executionStates store.Store + pendingStepRequests chan stepRequest + triggerEvents chan capabilities.CapabilityResponse + newWorkerCh chan struct{} + stepUpdateCh chan store.WorkflowExecutionStep + wg sync.WaitGroup + stopCh services.StopChan + newWorkerTimeout time.Duration + maxExecutionDuration time.Duration // testing lifecycle hook to signal when an execution is finished. onExecutionFinished func(string) @@ -53,6 +56,8 @@ type Engine struct { // Used for testing to control the retry interval // when initializing the engine. retryMs int + + clock clockwork.Clock } func (e *Engine) Start(ctx context.Context) error { @@ -183,7 +188,13 @@ func (e *Engine) init(ctx context.Context) { return } - e.logger.Debug("capabilities resolved, registering triggers") + e.logger.Debug("capabilities resolved, resuming in-progress workflows") + err := e.resumeInProgressExecutions(ctx) + if err != nil { + e.logger.Errorf("failed to resume workflows: %w", err) + } + + e.logger.Debug("registering triggers") for _, t := range e.workflow.triggers { err := e.registerTrigger(ctx, t) if err != nil { @@ -195,6 +206,55 @@ func (e *Engine) init(ctx context.Context) { e.afterInit(true) } +var ( + defaultOffset, defaultLimit = 0, 1_000 +) + +func (e *Engine) resumeInProgressExecutions(ctx context.Context) error { + wipExecutions, err := e.executionStates.GetUnfinished(ctx, defaultOffset, defaultLimit) + if err != nil { + return err + } + + // TODO: paginate properly + if len(wipExecutions) >= defaultLimit { + e.logger.Warnf("possible execution overflow during resumption") + } + + // Cache the dependents associated with a step. + // We may have to reprocess many executions, but should only + // need to calculate the dependents of a step once since + // they won't change. + refToDeps := map[string][]*step{} + for _, execution := range wipExecutions { + for _, step := range execution.Steps { + // NOTE: In order to determine what tasks need to be enqueued, + // we look at any completed steps, and for each dependent, + // check if they are ready to be enqueued. + // This will also handle an execution that has stalled immediately on creation, + // since we always create an execution with an initially completed trigger step. + if step.Status != store.StatusCompleted { + continue + } + + sds, ok := refToDeps[step.Ref] + if !ok { + s, err := e.workflow.dependents(step.Ref) + if err != nil { + return err + } + + sds = s + } + + for _, sd := range sds { + e.queueIfReady(execution, sd) + } + } + } + return nil +} + // initializeExecutionStrategy for `step`. // Broadly speaking, we'll use `immediateExecution` for non-target steps // and `scheduledExecution` for targets. If we don't have the necessary @@ -341,12 +401,12 @@ func (e *Engine) loop(ctx context.Context) { // Wait for a new worker to be available before dispatching a new one. // We'll do this up to newWorkerTimeout. If this expires, we'll put the // message back on the queue and keep going. - t := time.NewTimer(e.newWorkerTimeout) + t := e.clock.NewTimer(e.newWorkerTimeout) select { case <-e.newWorkerCh: e.wg.Add(1) go e.workerForStepRequest(ctx, pendingStepRequest) - case <-t.C: + case <-t.Chan(): e.logger.Errorf("timed out when spinning off worker for pending step request %+v", pendingStepRequest) e.pendingStepRequests <- pendingStepRequest } @@ -379,21 +439,23 @@ func generateExecutionID(workflowID, eventID string) (string, error) { // startExecution kicks off a new workflow execution when a trigger event is received. func (e *Engine) startExecution(ctx context.Context, executionID string, event values.Value) error { e.logger.Debugw("executing on a trigger event", "event", event, "executionID", executionID) - ec := &executionState{ - steps: map[string]*stepState{ + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ keywordTrigger: { - outputs: &stepOutput{ - value: event, + Outputs: &store.StepOutput{ + Value: event, }, - status: statusCompleted, + Status: store.StatusCompleted, + ExecutionID: executionID, + Ref: keywordTrigger, }, }, - workflowID: e.workflow.id, - executionID: executionID, - status: statusStarted, + WorkflowID: e.workflow.id, + ExecutionID: executionID, + Status: store.StatusStarted, } - err := e.executionStates.add(ctx, ec) + err := e.executionStates.Add(ctx, ec) if err != nil { return err } @@ -413,26 +475,25 @@ func (e *Engine) startExecution(ctx context.Context, executionID string, event v return nil } -func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) error { - state, err := e.executionStates.updateStep(ctx, &stepUpdate) +func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.WorkflowExecutionStep) error { + state, err := e.executionStates.UpsertStep(ctx, &stepUpdate) if err != nil { return err } - switch stepUpdate.status { - case statusCompleted: - stepDependents, err := e.workflow.dependents(stepUpdate.ref) + switch stepUpdate.Status { + case store.StatusCompleted: + stepDependents, err := e.workflow.dependents(stepUpdate.Ref) if err != nil { return err } // There are no steps left to process in the current path, so let's check if // we've completed the workflow. - // If not, we'll check for any dependents that are ready to process. if len(stepDependents) == 0 { workflowCompleted := true err := e.workflow.walkDo(keywordTrigger, func(s *step) error { - step, ok := state.steps[s.Ref] + step, ok := state.Steps[s.Ref] // The step is missing from the state, // which means it hasn't been processed yet. // Let's mark `workflowCompleted` = false, and @@ -442,8 +503,8 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err return nil } - switch step.status { - case statusCompleted, statusErrored: + switch step.Status { + case store.StatusCompleted, store.StatusErrored: default: workflowCompleted = false } @@ -454,18 +515,23 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err } if workflowCompleted { - err := e.finishExecution(ctx, state.executionID, statusCompleted) - if err != nil { - return err - } + return e.finishExecution(ctx, state.ExecutionID, store.StatusCompleted) } } + // We haven't completed the workflow, but should we continue? + // If we've been executing for too long, let's time the workflow out and stop here. + if state.CreatedAt != nil && e.clock.Since(*state.CreatedAt) > e.maxExecutionDuration { + return e.finishExecution(ctx, state.ExecutionID, store.StatusTimeout) + } + + // Finally, since the workflow hasn't timed out or completed, let's + // check for any dependents that are ready to process. for _, sd := range stepDependents { e.queueIfReady(state, sd) } - case statusErrored: - err := e.finishExecution(ctx, state.executionID, statusErrored) + case store.StatusErrored: + err := e.finishExecution(ctx, state.ExecutionID, store.StatusErrored) if err != nil { return err } @@ -474,11 +540,11 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err return nil } -func (e *Engine) queueIfReady(state executionState, step *step) { +func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { // Check if all dependencies are completed for the current step var waitingOnDependencies bool for _, dr := range step.dependencies { - stepState, ok := state.steps[dr] + stepState, ok := state.Steps[dr] if !ok { waitingOnDependencies = true continue @@ -489,7 +555,7 @@ func (e *Engine) queueIfReady(state executionState, step *step) { // This includes cases where one of the dependent // steps has errored, since that means we shouldn't // schedule the step for execution. - if stepState.status != statusCompleted { + if stepState.Status != store.StatusCompleted { waitingOnDependencies = true } } @@ -506,7 +572,7 @@ func (e *Engine) queueIfReady(state executionState, step *step) { func (e *Engine) finishExecution(ctx context.Context, executionID string, status string) error { e.logger.Infow("finishing execution", "executionID", executionID, "status", status) - err := e.executionStates.updateStatus(ctx, executionID, status) + err := e.executionStates.UpdateStatus(ctx, executionID, status) if err != nil { return err } @@ -521,27 +587,27 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // Instantiate a child logger; in addition to the WorkflowID field the workflow // logger will already have, this adds the `stepRef` and `executionID` - l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.executionID) + l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.ExecutionID) l.Debugw("executing on a step event") - stepState := &stepState{ - outputs: &stepOutput{}, - executionID: msg.state.executionID, - ref: msg.stepRef, + stepState := &store.WorkflowExecutionStep{ + Outputs: &store.StepOutput{}, + ExecutionID: msg.state.ExecutionID, + Ref: msg.stepRef, } inputs, outputs, err := e.executeStep(ctx, l, msg) if err != nil { l.Errorf("error executing step request: %s", err) - stepState.outputs.err = err - stepState.status = statusErrored + stepState.Outputs.Err = err + stepState.Status = store.StatusErrored } else { l.Infow("step executed successfully", "outputs", outputs) - stepState.outputs.value = outputs - stepState.status = statusCompleted + stepState.Outputs.Value = outputs + stepState.Status = store.StatusCompleted } - stepState.inputs = inputs + stepState.Inputs = inputs // Let's try and emit the stepUpdate. // If the context is canceled, we'll just drop the update. @@ -577,8 +643,8 @@ func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepReque Inputs: inputs, Config: step.config, Metadata: capabilities.RequestMetadata{ - WorkflowID: msg.state.workflowID, - WorkflowExecutionID: msg.state.executionID, + WorkflowID: msg.state.WorkflowID, + WorkflowExecutionID: msg.state.ExecutionID, }, } @@ -670,27 +736,31 @@ func (e *Engine) Close() error { } type Config struct { - Spec string - WorkflowID string - Lggr logger.Logger - Registry core.CapabilitiesRegistry - MaxWorkerLimit int - QueueSize int - NewWorkerTimeout time.Duration - DONInfo *capabilities.DON - PeerID func() *p2ptypes.PeerID + Spec string + WorkflowID string + Lggr logger.Logger + Registry core.CapabilitiesRegistry + MaxWorkerLimit int + QueueSize int + NewWorkerTimeout time.Duration + MaxExecutionDuration time.Duration + DONInfo *capabilities.DON + PeerID func() *p2ptypes.PeerID + Store store.Store // For testing purposes only maxRetries int retryMs int afterInit func(success bool) onExecutionFinished func(weid string) + clock clockwork.Clock } const ( - defaultWorkerLimit = 100 - defaultQueueSize = 100000 - defaultNewWorkerTimeout = 2 * time.Second + defaultWorkerLimit = 100 + defaultQueueSize = 100000 + defaultNewWorkerTimeout = 2 * time.Second + defaultMaxExecutionDuration = 10 * time.Minute ) func NewEngine(cfg Config) (engine *Engine, err error) { @@ -706,6 +776,14 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.NewWorkerTimeout = defaultNewWorkerTimeout } + if cfg.MaxExecutionDuration == 0 { + cfg.MaxExecutionDuration = defaultMaxExecutionDuration + } + + if cfg.Store == nil { + cfg.Store = store.NewInMemoryStore() + } + if cfg.retryMs == 0 { cfg.retryMs = 5000 } @@ -718,6 +796,10 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.onExecutionFinished = func(weid string) {} } + if cfg.clock == nil { + cfg.clock = clockwork.NewRealClock() + } + // TODO: validation of the workflow spec // We'll need to check, among other things: // - that there are no step `ref` called `trigger` as this is reserved for any triggers @@ -747,18 +829,20 @@ func NewEngine(cfg Config) (engine *Engine, err error) { DON: cfg.DONInfo, PeerID: cfg.PeerID, }, - executionStates: newInMemoryStore(), - pendingStepRequests: make(chan stepRequest, cfg.QueueSize), - newWorkerCh: newWorkerCh, - stepUpdateCh: make(chan stepState), - triggerEvents: make(chan capabilities.CapabilityResponse), - stopCh: make(chan struct{}), - newWorkerTimeout: cfg.NewWorkerTimeout, + executionStates: cfg.Store, + pendingStepRequests: make(chan stepRequest, cfg.QueueSize), + newWorkerCh: newWorkerCh, + stepUpdateCh: make(chan store.WorkflowExecutionStep), + triggerEvents: make(chan capabilities.CapabilityResponse), + stopCh: make(chan struct{}), + newWorkerTimeout: cfg.NewWorkerTimeout, + maxExecutionDuration: cfg.MaxExecutionDuration, onExecutionFinished: cfg.onExecutionFinished, afterInit: cfg.afterInit, maxRetries: cfg.maxRetries, retryMs: cfg.retryMs, + clock: cfg.clock, } return engine, nil } diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index ff4c5682129..212ad37367e 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -4,7 +4,9 @@ import ( "context" "errors" "testing" + "time" + "github.com/jonboulle/clockwork" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -13,8 +15,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/values" coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) const hardcodedWorkflow = ` @@ -71,7 +75,7 @@ type testHooks struct { } // newTestEngine creates a new engine with some test defaults. -func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (*Engine, *testHooks) { +func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { peerID := p2ptypes.PeerID{} initFailed := make(chan struct{}) executionFinished := make(chan string, 100) @@ -91,6 +95,10 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (*Engine, * onExecutionFinished: func(weid string) { executionFinished <- weid }, + clock: clockwork.NewFakeClock(), + } + for _, o := range opts { + o(&cfg) } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -152,14 +160,16 @@ func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request cap type mockTriggerCapability struct { capabilities.CapabilityInfo - triggerEvent capabilities.CapabilityResponse + triggerEvent *capabilities.CapabilityResponse ch chan capabilities.CapabilityResponse } var _ capabilities.TriggerCapability = (*mockTriggerCapability)(nil) func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - m.ch <- m.triggerEvent + if m.triggerEvent != nil { + m.ch <- *m.triggerEvent + } return m.ch, nil } @@ -169,47 +179,70 @@ func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capab func TestEngineWithHardcodedWorkflow(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) - reg := coreCap.NewRegistry(logger.TestLogger(t)) - trigger, cr := mockTrigger(t) - - require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - target1 := mockTarget() - require.NoError(t, reg.Add(ctx, target1)) - - target2 := newMockCapability( - capabilities.MustNewCapabilityInfo( - "write_ethereum-testnet-sepolia", - capabilities.CapabilityTypeTarget, - "a write capability targeting ethereum sepolia testnet", - "v1.0.0", - nil, - ), - func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - m := req.Inputs.Underlying["report"].(*values.Map) - return capabilities.CapabilityResponse{ - Value: m, - }, nil + testCases := []struct { + name string + store store.Store + }{ + { + name: "db-engine", + store: store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()), }, - ) - require.NoError(t, reg.Add(ctx, target2)) - - eng, hooks := newTestEngine(t, reg, hardcodedWorkflow) - - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() - - eid := getExecutionId(t, eng, hooks) - assert.Equal(t, cr, <-target1.response) - assert.Equal(t, cr, <-target2.response) - - state, err := eng.executionStates.get(ctx, eid) - require.NoError(t, err) - - assert.Equal(t, state.status, statusCompleted) + { + name: "in-memory-engine", + store: store.NewInMemoryStore(), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, cr := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + target1 := mockTarget() + require.NoError(t, reg.Add(ctx, target1)) + + target2 := newMockCapability( + capabilities.MustNewCapabilityInfo( + "write_ethereum-testnet-sepolia", + capabilities.CapabilityTypeTarget, + "a write capability targeting ethereum sepolia testnet", + "v1.0.0", + nil, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + m := req.Inputs.Underlying["report"].(*values.Map) + return capabilities.CapabilityResponse{ + Value: m, + }, nil + }, + ) + require.NoError(t, reg.Add(ctx, target2)) + + eng, testHooks := newTestEngine( + t, + reg, + hardcodedWorkflow, + func(c *Config) { c.Store = tc.store }, + ) + + err := eng.Start(ctx) + require.NoError(t, err) + defer eng.Close() + + eid := getExecutionId(t, eng, testHooks) + assert.Equal(t, cr, <-target1.response) + assert.Equal(t, cr, <-target2.response) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompleted) + }) + } } const ( @@ -275,10 +308,24 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap cr := capabilities.CapabilityResponse{ Value: resp, } - mt.triggerEvent = cr + mt.triggerEvent = &cr return mt, cr } +func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { + mt := &mockTriggerCapability{ + CapabilityInfo: capabilities.MustNewCapabilityInfo( + "mercury-trigger", + capabilities.CapabilityTypeTrigger, + "issues a trigger when a mercury report is received.", + "v1.0.0", + nil, + ), + ch: make(chan capabilities.CapabilityResponse, 10), + } + return mt +} + func mockFailingConsensus() *mockCapability { return newMockCapability( capabilities.MustNewCapabilityInfo( @@ -357,12 +404,12 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { defer eng.Close() eid := getExecutionId(t, eng, hooks) - state, err := eng.executionStates.get(ctx, eid) + state, err := eng.executionStates.Get(ctx, eid) require.NoError(t, err) - assert.Equal(t, state.status, statusErrored) + assert.Equal(t, state.Status, store.StatusErrored) // evm_median is the ref of our failing consensus step - assert.Equal(t, state.steps["evm_median"].status, statusErrored) + assert.Equal(t, state.Steps["evm_median"].Status, store.StatusErrored) } const ( @@ -455,14 +502,14 @@ func TestEngine_MultiStepDependencies(t *testing.T) { defer eng.Close() eid := getExecutionId(t, eng, hooks) - state, err := eng.executionStates.get(ctx, eid) + state, err := eng.executionStates.Get(ctx, eid) require.NoError(t, err) - assert.Equal(t, state.status, statusCompleted) + assert.Equal(t, state.Status, store.StatusCompleted) // The inputs to the consensus step should // be the outputs of the two dependents. - inputs := state.steps["evm_median"].inputs + inputs := state.Steps["evm_median"].Inputs unw, err := values.Unwrap(inputs) require.NoError(t, err) @@ -477,3 +524,116 @@ func TestEngine_MultiStepDependencies(t *testing.T) { require.NoError(t, err) assert.Equal(t, obs.([]any)[1], o) } + +func TestEngine_ResumesPendingExecutions(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger := mockNoopTrigger(t) + resp, err := values.NewMap(map[string]any{ + "123": decimal.NewFromFloat(1.00), + "456": decimal.NewFromFloat(1.25), + "789": decimal.NewFromFloat(1.50), + }) + require.NoError(t, err) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + action, _ := mockAction() + require.NoError(t, reg.Add(ctx, action)) + + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()) + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ + keywordTrigger: { + Outputs: &store.StepOutput{ + Value: resp, + }, + Status: store.StatusCompleted, + ExecutionID: "", + Ref: keywordTrigger, + }, + }, + WorkflowID: "", + ExecutionID: "", + Status: store.StatusStarted, + } + err = dbstore.Add(ctx, ec) + require.NoError(t, err) + + eng, hooks := newTestEngine( + t, + reg, + multiStepWorkflow, + func(c *Config) { c.Store = dbstore }, + ) + err = eng.Start(ctx) + require.NoError(t, err) + + eid := getExecutionId(t, eng, hooks) + gotEx, err := dbstore.Get(ctx, eid) + require.NoError(t, err) + assert.Equal(t, store.StatusCompleted, gotEx.Status) +} + +func TestEngine_TimesOutOldExecutions(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger := mockNoopTrigger(t) + resp, err := values.NewMap(map[string]any{ + "123": decimal.NewFromFloat(1.00), + "456": decimal.NewFromFloat(1.25), + "789": decimal.NewFromFloat(1.50), + }) + require.NoError(t, err) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + action, _ := mockAction() + require.NoError(t, reg.Add(ctx, action)) + + clock := clockwork.NewFakeClock() + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ + keywordTrigger: { + Outputs: &store.StepOutput{ + Value: resp, + }, + Status: store.StatusCompleted, + ExecutionID: "", + Ref: keywordTrigger, + }, + }, + WorkflowID: "", + ExecutionID: "", + Status: store.StatusStarted, + } + err = dbstore.Add(ctx, ec) + require.NoError(t, err) + + eng, hooks := newTestEngine( + t, + reg, + multiStepWorkflow, + func(c *Config) { + c.Store = dbstore + c.clock = clock + }, + ) + clock.Advance(15 * time.Minute) + err = eng.Start(ctx) + require.NoError(t, err) + + _ = getExecutionId(t, eng, hooks) + gotEx, err := dbstore.Get(ctx, "") + require.NoError(t, err) + assert.Equal(t, store.StatusTimeout, gotEx.Status) +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index cd167403089..8dce11cabe5 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -8,11 +8,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) type stepRequest struct { stepRef string - state executionState + state store.WorkflowExecution } // stepDefinition is the parsed representation of a step in a workflow. diff --git a/core/services/workflows/state.go b/core/services/workflows/state.go index c229b14e1dd..4026a59be0b 100644 --- a/core/services/workflows/state.go +++ b/core/services/workflows/state.go @@ -6,71 +6,44 @@ import ( "strconv" "strings" - "github.com/smartcontractkit/chainlink-common/pkg/values" -) + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" -const ( - statusStarted = "started" - statusErrored = "errored" - statusTimeout = "timeout" - statusCompleted = "completed" + "github.com/smartcontractkit/chainlink-common/pkg/values" ) -type stepOutput struct { - err error - value values.Value -} - -type stepState struct { - executionID string - ref string - status string - - inputs *values.Map - outputs *stepOutput -} - -type executionState struct { - steps map[string]*stepState - executionID string - workflowID string - - status string -} - // copyState returns a deep copy of the input executionState -func copyState(es executionState) executionState { - steps := map[string]*stepState{} - for ref, step := range es.steps { +func copyState(es store.WorkflowExecution) store.WorkflowExecution { + steps := map[string]*store.WorkflowExecutionStep{} + for ref, step := range es.Steps { var mval *values.Map - if step.inputs != nil { - mp := values.Proto(step.inputs).GetMapValue() + if step.Inputs != nil { + mp := values.Proto(step.Inputs).GetMapValue() mval = values.FromMapValueProto(mp) } - op := values.Proto(step.outputs.value) + op := values.Proto(step.Outputs.Value) copiedov := values.FromProto(op) - newState := &stepState{ - executionID: step.executionID, - ref: step.ref, - status: step.status, + newState := &store.WorkflowExecutionStep{ + ExecutionID: step.ExecutionID, + Ref: step.Ref, + Status: step.Status, - outputs: &stepOutput{ - err: step.outputs.err, - value: copiedov, + Outputs: &store.StepOutput{ + Err: step.Outputs.Err, + Value: copiedov, }, - inputs: mval, + Inputs: mval, } steps[ref] = newState } - return executionState{ - executionID: es.executionID, - workflowID: es.workflowID, - status: es.status, - steps: steps, + return store.WorkflowExecution{ + ExecutionID: es.ExecutionID, + WorkflowID: es.WorkflowID, + Status: es.Status, + Steps: steps, } } @@ -84,7 +57,7 @@ func copyState(es executionState) executionState { // If a key has more than two parts, then we traverse the parts // to find the value we want to replace. // We support traversing both nested maps and lists and any combination of the two. -func interpolateKey(key string, state executionState) (any, error) { +func interpolateKey(key string, state store.WorkflowExecution) (any, error) { parts := strings.Split(key, ".") if len(parts) < 2 { @@ -92,7 +65,7 @@ func interpolateKey(key string, state executionState) (any, error) { } // lookup the step we want to get either input or output state from - sc, ok := state.steps[parts[0]] + sc, ok := state.Steps[parts[0]] if !ok { return "", fmt.Errorf("could not find ref `%s`", parts[0]) } @@ -100,13 +73,13 @@ func interpolateKey(key string, state executionState) (any, error) { var value values.Value switch parts[1] { case "inputs": - value = sc.inputs + value = sc.Inputs case "outputs": - if sc.outputs.err != nil { + if sc.Outputs.Err != nil { return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: step has errored", parts[1], sc) } - value = sc.outputs.value + value = sc.Outputs.Value default: return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: second part must be `inputs` or `outputs`", parts[1], sc) } @@ -153,7 +126,7 @@ var ( // identifies any values that should be replaced from `state`. // // A value `v` should be replaced if it is wrapped as follows: `$(v)`. -func findAndInterpolateAllKeys(input any, state executionState) (any, error) { +func findAndInterpolateAllKeys(input any, state store.WorkflowExecution) (any, error) { return deepMap( input, func(el string) (any, error) { diff --git a/core/services/workflows/state_test.go b/core/services/workflows/state_test.go index 0917662ccb6..ccd6cd5004d 100644 --- a/core/services/workflows/state_test.go +++ b/core/services/workflows/state_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) func TestInterpolateKey(t *testing.T) { @@ -27,18 +28,18 @@ func TestInterpolateKey(t *testing.T) { testCases := []struct { name string key string - state executionState + state store.WorkflowExecution expected any errMsg string }{ { name: "digging into a string", key: "evm_median.outputs.reports", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -48,27 +49,27 @@ func TestInterpolateKey(t *testing.T) { { name: "ref doesn't exist", key: "evm_median.outputs.reports", - state: executionState{ - steps: map[string]*stepState{}, + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{}, }, errMsg: "could not find ref `evm_median`", }, { name: "less than 2 parts", key: "evm_median", - state: executionState{ - steps: map[string]*stepState{}, + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{}, }, errMsg: "must have at least two parts", }, { name: "second part isn't `inputs` or `outputs`", key: "evm_median.foo", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -78,11 +79,11 @@ func TestInterpolateKey(t *testing.T) { { name: "outputs has errored", key: "evm_median.outputs", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - err: errors.New("catastrophic error"), + Outputs: &store.StepOutput{ + Err: errors.New("catastrophic error"), }, }, }, @@ -92,11 +93,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into a recursive map", key: "evm_median.outputs.reports.inner", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -106,11 +107,11 @@ func TestInterpolateKey(t *testing.T) { { name: "missing key in map", key: "evm_median.outputs.reports.missing", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -120,11 +121,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array", key: "evm_median.outputs.reportsList.0", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -134,11 +135,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array that's too small", key: "evm_median.outputs.reportsList.2", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -148,11 +149,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array with a string key", key: "evm_median.outputs.reportsList.notAString", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -162,11 +163,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array with a negative index", key: "evm_median.outputs.reportsList.-1", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -176,11 +177,11 @@ func TestInterpolateKey(t *testing.T) { { name: "empty element", key: "evm_median.outputs..notAString", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -207,7 +208,7 @@ func TestInterpolateInputsFromState(t *testing.T) { testCases := []struct { name string inputs map[string]any - state executionState + state store.WorkflowExecution expected any errMsg string }{ @@ -218,11 +219,11 @@ func TestInterpolateInputsFromState(t *testing.T) { "shouldinterpolate": "$(evm_median.outputs)", }, }, - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -238,11 +239,11 @@ func TestInterpolateInputsFromState(t *testing.T) { inputs: map[string]any{ "foo": "bar", }, - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, diff --git a/core/services/workflows/store.go b/core/services/workflows/store.go deleted file mode 100644 index d6ef72d39b9..00000000000 --- a/core/services/workflows/store.go +++ /dev/null @@ -1,70 +0,0 @@ -package workflows - -import ( - "context" - "fmt" - "sync" -) - -// `inMemoryStore` is a temporary in-memory -// equivalent of the database table that should persist -// workflow progress. -type inMemoryStore struct { - idToState map[string]*executionState - mu sync.RWMutex -} - -func newInMemoryStore() *inMemoryStore { - return &inMemoryStore{idToState: map[string]*executionState{}} -} - -// add adds a new execution state under the given executionID -func (s *inMemoryStore) add(ctx context.Context, state *executionState) error { - s.mu.Lock() - defer s.mu.Unlock() - _, ok := s.idToState[state.executionID] - if ok { - return fmt.Errorf("execution ID %s already exists in store", state.executionID) - } - - s.idToState[state.executionID] = state - return nil -} - -// updateStep updates a step for the given executionID -func (s *inMemoryStore) updateStep(ctx context.Context, step *stepState) (executionState, error) { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[step.executionID] - if !ok { - return executionState{}, fmt.Errorf("could not find execution %s", step.executionID) - } - - state.steps[step.ref] = step - return *state, nil -} - -// updateStatus updates the status for the given executionID -func (s *inMemoryStore) updateStatus(ctx context.Context, executionID string, status string) error { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[executionID] - if !ok { - return fmt.Errorf("could not find execution %s", executionID) - } - - state.status = status - return nil -} - -// get gets the state for the given executionID -func (s *inMemoryStore) get(ctx context.Context, executionID string) (executionState, error) { - s.mu.RLock() - defer s.mu.RUnlock() - state, ok := s.idToState[executionID] - if !ok { - return executionState{}, fmt.Errorf("could not find execution %s", executionID) - } - - return *state, nil -} diff --git a/core/services/workflows/store/models.go b/core/services/workflows/store/models.go new file mode 100644 index 00000000000..29a1df154de --- /dev/null +++ b/core/services/workflows/store/models.go @@ -0,0 +1,41 @@ +package store + +import ( + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +const ( + StatusStarted = "started" + StatusErrored = "errored" + StatusTimeout = "timeout" + StatusCompleted = "completed" +) + +type StepOutput struct { + Err error + Value values.Value +} + +type WorkflowExecutionStep struct { + ExecutionID string + Ref string + Status string + + Inputs *values.Map + Outputs *StepOutput + + UpdatedAt *time.Time +} + +type WorkflowExecution struct { + Steps map[string]*WorkflowExecutionStep + ExecutionID string + WorkflowID string + + Status string + CreatedAt *time.Time + UpdatedAt *time.Time + FinishedAt *time.Time +} diff --git a/core/services/workflows/store/store.go b/core/services/workflows/store/store.go new file mode 100644 index 00000000000..e77050617ab --- /dev/null +++ b/core/services/workflows/store/store.go @@ -0,0 +1,16 @@ +package store + +import ( + "context" +) + +type Store interface { + Add(ctx context.Context, state *WorkflowExecution) error + UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) + UpdateStatus(ctx context.Context, executionID string, status string) error + Get(ctx context.Context, executionID string) (WorkflowExecution, error) + GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) +} + +var _ Store = (*InMemoryStore)(nil) +var _ Store = (*DBStore)(nil) diff --git a/core/services/workflows/store/store_db.go b/core/services/workflows/store/store_db.go new file mode 100644 index 00000000000..73acece5b18 --- /dev/null +++ b/core/services/workflows/store/store_db.go @@ -0,0 +1,382 @@ +package store + +import ( + "context" + "errors" + "fmt" + "time" + + "google.golang.org/protobuf/proto" + + "github.com/jmoiron/sqlx" + "github.com/jonboulle/clockwork" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/values" + valuespb "github.com/smartcontractkit/chainlink-common/pkg/values/pb" +) + +// `DBStore` is a postgres-backed +// data store that persists workflow progress. +type DBStore struct { + db sqlutil.DataSource + clock clockwork.Clock +} + +// `workflowExecutionRow` describes a row +// of the `workflow_executions` table +type workflowExecutionRow struct { + ID string + WorkflowID *string + Status string + CreatedAt *time.Time + UpdatedAt *time.Time + FinishedAt *time.Time +} + +// `workflowStepRow` describes a row +// of the `workflow_steps` table +type workflowStepRow struct { + ID uint + WorkflowExecutionID string `db:"workflow_execution_id"` + Ref string + Status string + Inputs []byte + OutputErr *string `db:"output_err"` + OutputValue []byte `db:"output_value"` + UpdatedAt *time.Time `db:"updated_at"` +} + +// `UpdateStatus` updates the status of the given workflow execution +func (d *DBStore) UpdateStatus(ctx context.Context, executionID string, status string) error { + sql := `UPDATE workflow_executions SET status = $1, updated_at = $2 WHERE id = $3` + + // If we're completing the workflow execution, let's also set a finished_at timestamp. + if status != StatusStarted { + sql = "UPDATE workflow_executions SET status = $1, updated_at = $2, finished_at = $2 WHERE id = $3" + } + _, err := d.db.ExecContext(ctx, sql, status, d.clock.Now(), executionID) + return err +} + +// `UpsertStep` updates the given step. This will correspond to an insert, or an update +// depending on whether a step with the ref already exists. +func (d *DBStore) UpsertStep(ctx context.Context, stepState *WorkflowExecutionStep) (WorkflowExecution, error) { + step, err := stateToStep(stepState) + if err != nil { + return WorkflowExecution{}, err + } + + err = d.upsertSteps(ctx, []workflowStepRow{step}) + if err != nil { + return WorkflowExecution{}, err + } + + return d.Get(ctx, step.WorkflowExecutionID) +} + +// `Get` fetches the ExecutionState from the database. +func (d *DBStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { + wex := &workflowExecutionRow{} + err := d.db.GetContext(ctx, wex, `SELECT * FROM workflow_executions WHERE id = $1`, executionID) + if err != nil { + return WorkflowExecution{}, err + } + + ws := []workflowStepRow{} + err = d.db.SelectContext(ctx, &ws, `SELECT * FROM workflow_steps WHERE workflow_execution_id = $1`, wex.ID) + if err != nil { + return WorkflowExecution{}, err + } + + refToStep := map[string]*WorkflowExecutionStep{} + for _, s := range ws { + ss, err := stepToState(s) + if err != nil { + return WorkflowExecution{}, err + } + + refToStep[s.Ref] = ss + } + + var workflowID string + if wex.WorkflowID != nil { + workflowID = *wex.WorkflowID + } + + es := WorkflowExecution{ + ExecutionID: wex.ID, + WorkflowID: workflowID, + Status: wex.Status, + Steps: refToStep, + CreatedAt: wex.CreatedAt, + UpdatedAt: wex.UpdatedAt, + FinishedAt: wex.FinishedAt, + } + return es, nil +} + +func stepToState(step workflowStepRow) (*WorkflowExecutionStep, error) { + var inputs *values.Map + if len(step.Inputs) > 0 { + vmProto := &valuespb.Map{} + err := proto.Unmarshal(step.Inputs, vmProto) + if err != nil { + return nil, err + } + + inputs = values.FromMapValueProto(vmProto) + } + + var ( + outputErr error + outputs values.Value + ) + + if step.OutputErr != nil { + outputErr = errors.New(*step.OutputErr) + } + + if len(step.OutputValue) != 0 { + vProto := &valuespb.Value{} + err := proto.Unmarshal(step.OutputValue, vProto) + if err != nil { + return nil, err + } + + outputs = values.FromProto(vProto) + } + + var so *StepOutput + if outputErr != nil || outputs != nil { + so = &StepOutput{ + Err: outputErr, + Value: outputs, + } + } + + return &WorkflowExecutionStep{ + ExecutionID: step.WorkflowExecutionID, + Ref: step.Ref, + Status: step.Status, + Inputs: inputs, + Outputs: so, + }, nil +} + +func stateToStep(state *WorkflowExecutionStep) (workflowStepRow, error) { + var inpb []byte + if state.Inputs != nil { + p := values.Proto(state.Inputs).GetMapValue() + ib, err := proto.Marshal(p) + if err != nil { + return workflowStepRow{}, err + } + inpb = ib + } + + wsr := workflowStepRow{ + WorkflowExecutionID: state.ExecutionID, + Ref: state.Ref, + Status: state.Status, + Inputs: inpb, + } + + if state.Outputs == nil { + return wsr, nil + } + + if state.Outputs.Value != nil { + p := values.Proto(state.Outputs.Value) + ob, err := proto.Marshal(p) + if err != nil { + return workflowStepRow{}, err + } + + wsr.OutputValue = ob + } + + if state.Outputs.Err != nil { + errs := state.Outputs.Err.Error() + wsr.OutputErr = &errs + } + return wsr, nil +} + +// `Add` creates the relevant workflow_execution and workflow_step entries +// to persist the passed in ExecutionState. +func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { + return d.transact(ctx, func(db *DBStore) error { + var wid *string + if state.WorkflowID != "" { + wid = &state.WorkflowID + } + wex := &workflowExecutionRow{ + ID: state.ExecutionID, + WorkflowID: wid, + Status: state.Status, + } + err := db.insertWorkflowExecution(ctx, wex) + if err != nil { + return fmt.Errorf("could not insert workflow execution %s: %w", state.ExecutionID, err) + } + + ws := []workflowStepRow{} + for _, step := range state.Steps { + step, err := stateToStep(step) + if err != nil { + return err + } + ws = append(ws, step) + } + if len(ws) > 0 { + return db.upsertSteps(ctx, ws) + } + return nil + }) +} + +func (d *DBStore) upsertSteps(ctx context.Context, steps []workflowStepRow) error { + for _, s := range steps { + now := d.clock.Now() + s.UpdatedAt = &now + } + + sql := ` + INSERT INTO + workflow_steps(workflow_execution_id, ref, status, inputs, output_err, output_value, updated_at) + VALUES (:workflow_execution_id, :ref, :status, :inputs, :output_err, :output_value, :updated_at) + ON CONFLICT ON CONSTRAINT uniq_workflow_execution_id_ref + DO UPDATE SET + workflow_execution_id = EXCLUDED.workflow_execution_id, + ref = EXCLUDED.ref, + status = EXCLUDED.status, + inputs = EXCLUDED.inputs, + output_err = EXCLUDED.output_err, + output_value = EXCLUDED.output_value, + updated_at = EXCLUDED.updated_at; + ` + stmt, args, err := sqlx.Named(sql, steps) + if err != nil { + return err + } + stmt = d.db.Rebind(stmt) + _, err = d.db.ExecContext(ctx, stmt, args...) + return err +} + +func (d *DBStore) insertWorkflowExecution(ctx context.Context, execution *workflowExecutionRow) error { + sql := ` + INSERT INTO + workflow_executions(id, workflow_id, status, created_at) + VALUES ($1, $2, $3, $4) + ` + _, err := d.db.ExecContext(ctx, sql, execution.ID, execution.WorkflowID, execution.Status, d.clock.Now()) + return err +} + +func (d *DBStore) transact(ctx context.Context, fn func(*DBStore) error) error { + return sqlutil.Transact( + ctx, + func(ds sqlutil.DataSource) *DBStore { + return &DBStore{db: ds, clock: d.clock} + }, + d.db, + nil, + fn, + ) +} + +func (d *DBStore) GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) { + sql := ` + SELECT + workflow_steps.workflow_execution_id AS ws_workflow_execution_id, + workflow_steps.ref AS ws_ref, + workflow_steps.status AS ws_status, + workflow_steps.inputs AS ws_inputs, + workflow_steps.output_err AS ws_output_err, + workflow_steps.output_value AS ws_output_value, + workflow_steps.updated_at AS ws_updated_at, + workflow_executions.id AS we_id, + workflow_executions.workflow_id AS we_workflow_id, + workflow_executions.status AS we_status, + workflow_executions.created_at AS we_created_at, + workflow_executions.updated_at AS we_updated_at, + workflow_executions.finished_at AS we_finished_at + FROM workflow_executions + JOIN workflow_steps + ON workflow_steps.workflow_execution_id = workflow_executions.id + WHERE workflow_executions.status = $1 + ORDER BY workflow_executions.created_at DESC + LIMIT $2 + OFFSET $3 + ` + joinRecords := []struct { + // WorkflowExecutionStep fields + WSWorkflowExecutionID string `db:"ws_workflow_execution_id"` + WSRef string `db:"ws_ref"` + WSStatus string `db:"ws_status"` + WSInputs []byte `db:"ws_inputs"` + WSOutputErr *string `db:"ws_output_err"` + WSOutputValue []byte `db:"ws_output_value"` + WSUpdatedAt *time.Time `db:"ws_updated_at"` + + // WorkflowExecution fields + WEID string `db:"we_id"` + WEWorkflowID *string `db:"we_workflow_id"` + WEStatus string `db:"we_status"` + WECreatedAt *time.Time `db:"we_created_at"` + WEUpdatedAt *time.Time `db:"we_updated_at"` + WEFinishedAt *time.Time `db:"we_finished_at"` + }{} + err := d.db.SelectContext(ctx, &joinRecords, sql, StatusStarted, limit, offset) + if err != nil { + return []WorkflowExecution{}, err + } + + idToExecutionState := map[string]*WorkflowExecution{} + for _, jr := range joinRecords { + var wid string + if jr.WEWorkflowID != nil { + wid = *jr.WEWorkflowID + } + if _, ok := idToExecutionState[jr.WEID]; !ok { + idToExecutionState[jr.WEID] = &WorkflowExecution{ + ExecutionID: jr.WEID, + WorkflowID: wid, + Status: jr.WEStatus, + Steps: map[string]*WorkflowExecutionStep{}, + CreatedAt: jr.WECreatedAt, + UpdatedAt: jr.WEUpdatedAt, + FinishedAt: jr.WEFinishedAt, + } + } + + state, err := stepToState(workflowStepRow{ + WorkflowExecutionID: jr.WSWorkflowExecutionID, + Ref: jr.WSRef, + OutputErr: jr.WSOutputErr, + OutputValue: jr.WSOutputValue, + Inputs: jr.WSInputs, + Status: jr.WSStatus, + UpdatedAt: jr.WSUpdatedAt, + }) + if err != nil { + return nil, err + } + + es := idToExecutionState[jr.WEID] + es.Steps[state.Ref] = state + } + + states := []WorkflowExecution{} + for _, s := range idToExecutionState { + states = append(states, *s) + } + + return states, nil +} + +func NewDBStore(ds sqlutil.DataSource, clock clockwork.Clock) *DBStore { + return &DBStore{db: ds, clock: clock} +} diff --git a/core/services/workflows/store/store_db_test.go b/core/services/workflows/store/store_db_test.go new file mode 100644 index 00000000000..e41f4857363 --- /dev/null +++ b/core/services/workflows/store/store_db_test.go @@ -0,0 +1,215 @@ +package store + +import ( + "crypto/rand" + "encoding/hex" + "errors" + "testing" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" +) + +func randomID() string { + b := make([]byte, 32) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + return hex.EncodeToString(b) +} + +func Test_StoreDB(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + gotEs, err := store.Get(tests.Context(t), es.ExecutionID) + // Zero out the created at timestamp; this isn't present on `es` + // but is added by the db store. + gotEs.CreatedAt = nil + require.NoError(t, err) + assert.Equal(t, es, gotEs) +} + +func Test_StoreDB_DuplicateEntry(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + err = store.Add(tests.Context(t), &es) + assert.ErrorContains(t, err, "duplicate key value violates") +} + +func Test_StoreDB_UpdateStatus(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + completedStatus := "completed" + err = store.UpdateStatus(tests.Context(t), es.ExecutionID, "completed") + require.NoError(t, err) + + gotEs, err := store.Get(tests.Context(t), es.ExecutionID) + require.NoError(t, err) + + assert.Equal(t, gotEs.Status, completedStatus) +} + +func Test_StoreDB_UpdateStep(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: "completed", + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: "started", + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + stepOne.Status = "completed" + nm, err := values.NewMap(map[string]any{"hello": "world"}) + require.NoError(t, err) + + stepOne.Inputs = nm + stepOne.Outputs = &StepOutput{Err: errors.New("some error")} + + es, err = store.UpsertStep(tests.Context(t), stepOne) + require.NoError(t, err) + + gotStep := es.Steps[stepOne.Ref] + assert.Equal(t, stepOne, gotStep) + + stepTwo.Outputs = &StepOutput{Value: nm} + es, err = store.UpsertStep(tests.Context(t), stepTwo) + require.NoError(t, err) + + gotStep = es.Steps[stepTwo.Ref] + assert.Equal(t, stepTwo, gotStep) +} + +func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: "completed", + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: "started", + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + id = randomID() + esTwo := WorkflowExecution{ + ExecutionID: id, + Status: "completed", + Steps: map[string]*WorkflowExecutionStep{}, + } + err = store.Add(tests.Context(t), &esTwo) + require.NoError(t, err) + + states, err := store.GetUnfinished(tests.Context(t), 0, 100) + require.NoError(t, err) + + assert.Len(t, states, 1) + // Zero out the completedAt timestamp + states[0].CreatedAt = nil + assert.Equal(t, es, states[0]) +} diff --git a/core/services/workflows/store/store_memory.go b/core/services/workflows/store/store_memory.go new file mode 100644 index 00000000000..7c8226c5d9c --- /dev/null +++ b/core/services/workflows/store/store_memory.go @@ -0,0 +1,86 @@ +package store + +import ( + "context" + "fmt" + "sync" +) + +// `InMemoryStore` is a temporary in-memory +// equivalent of the database table that should persist +// workflow progress. +type InMemoryStore struct { + idToState map[string]*WorkflowExecution + mu sync.RWMutex +} + +func NewInMemoryStore() *InMemoryStore { + return &InMemoryStore{idToState: map[string]*WorkflowExecution{}} +} + +// Add adds a new execution state under the given executionID +func (s *InMemoryStore) Add(ctx context.Context, state *WorkflowExecution) error { + s.mu.Lock() + defer s.mu.Unlock() + _, ok := s.idToState[state.ExecutionID] + if ok { + return fmt.Errorf("execution ID %s already exists in store", state.ExecutionID) + } + + s.idToState[state.ExecutionID] = state + return nil +} + +// UpsertStep updates a step for the given executionID +func (s *InMemoryStore) UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) { + s.mu.Lock() + defer s.mu.Unlock() + state, ok := s.idToState[step.ExecutionID] + if !ok { + return WorkflowExecution{}, fmt.Errorf("could not find execution %s", step.ExecutionID) + } + + state.Steps[step.Ref] = step + return *state, nil +} + +// UpdateStatus updates the status for the given executionID +func (s *InMemoryStore) UpdateStatus(ctx context.Context, executionID string, status string) error { + s.mu.Lock() + defer s.mu.Unlock() + state, ok := s.idToState[executionID] + if !ok { + return fmt.Errorf("could not find execution %s", executionID) + } + + state.Status = status + return nil +} + +// Get gets the state for the given executionID +func (s *InMemoryStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { + s.mu.RLock() + defer s.mu.RUnlock() + state, ok := s.idToState[executionID] + if !ok { + return WorkflowExecution{}, fmt.Errorf("could not find execution %s", executionID) + } + + return *state, nil +} + +// GetUnfinished gets the states for execution that are in a started state +// Offset and limit are ignored for the in-memory store. +func (s *InMemoryStore) GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + states := []WorkflowExecution{} + for _, s := range s.idToState { + if s.Status == StatusStarted { + states = append(states, *s) + } + } + + return states, nil +} diff --git a/core/store/migrate/migrations/0235_add_workflow_models.sql b/core/store/migrate/migrations/0235_add_workflow_models.sql new file mode 100644 index 00000000000..bd159b3a9d2 --- /dev/null +++ b/core/store/migrate/migrations/0235_add_workflow_models.sql @@ -0,0 +1,47 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TYPE workflow_status AS ENUM ( + 'started', + 'errored', + 'timeout', + 'completed' +); + +ALTER TABLE workflow_specs + ADD CONSTRAINT fk_unique_workflow_id unique(workflow_id); + +CREATE TABLE workflow_executions ( + id varchar(64) PRIMARY KEY, + workflow_id varchar(64) references workflow_specs(workflow_id), + status workflow_status NOT NULL, + created_at timestamp with time zone, + updated_at timestamp with time zone, + finished_at timestamp with time zone +); + +CREATE TABLE workflow_steps ( + id SERIAL PRIMARY KEY, + workflow_execution_id varchar(64) references workflow_executions(id) NOT NULL, + ref text NOT NULL, + status workflow_status NOT NULL, + inputs bytea, + output_err text, + output_value bytea, + updated_at timestamp with time zone +); + +ALTER TABLE workflow_steps + ADD CONSTRAINT uniq_workflow_execution_id_ref unique(workflow_execution_id, ref); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE workflow_steps + DROP CONSTRAINT uniq_workflow_execution_id_ref; +DROP TABLE workflow_steps; +DROP TABLE workflow_executions; +ALTER TABLE workflow_specs + DROP CONSTRAINT fk_unique_workflow_id; +DROP TYPE workflow_status; +-- +goose StatementEnd From 466d1617607712263657029adf7ff4dd9713b3b3 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Mon, 6 May 2024 13:30:35 -0400 Subject: [PATCH 21/35] Fix race condition in Poller tests (#13110) * Create polling channel * Update poller_test.go --- common/client/poller.go | 8 +++++--- common/client/poller_test.go | 40 ++++++++---------------------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/common/client/poller.go b/common/client/poller.go index ebdcbd66283..d6080722c5c 100644 --- a/common/client/poller.go +++ b/common/client/poller.go @@ -27,10 +27,11 @@ type Poller[T any] struct { wg sync.WaitGroup } -// NewPoller creates a new Poller instance +// NewPoller creates a new Poller instance and returns a channel to receive the polled data func NewPoller[ T any, -](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, channel chan<- T, logger logger.Logger) Poller[T] { +](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, logger logger.Logger) (Poller[T], <-chan T) { + channel := make(chan T) return Poller[T]{ pollingInterval: pollingInterval, pollingFunc: pollingFunc, @@ -39,7 +40,7 @@ func NewPoller[ logger: logger, errCh: make(chan error), stopCh: make(chan struct{}), - } + }, channel } var _ types.Subscription = &Poller[any]{} @@ -58,6 +59,7 @@ func (p *Poller[T]) Unsubscribe() { close(p.stopCh) p.wg.Wait() close(p.errCh) + close(p.channel) return nil }) } diff --git a/common/client/poller_test.go b/common/client/poller_test.go index 3f11c759adb..82a05b5dfc7 100644 --- a/common/client/poller_test.go +++ b/common/client/poller_test.go @@ -23,10 +23,7 @@ func Test_Poller(t *testing.T) { return nil, nil } - channel := make(chan Head, 1) - defer close(channel) - - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) @@ -50,12 +47,8 @@ func Test_Poller(t *testing.T) { return h.ToMockHead(t), nil } - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - // Create poller and start to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -79,14 +72,10 @@ func Test_Poller(t *testing.T) { return nil, fmt.Errorf("polling error %d", pollNumber) } - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, olggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -114,14 +103,10 @@ func Test_Poller(t *testing.T) { // Set instant timeout pollingTimeout := time.Duration(0) - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -146,14 +131,10 @@ func Test_Poller(t *testing.T) { // Set long timeout pollingTimeout := time.Minute - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) require.NoError(t, poller.Start()) // Unsubscribe while blocked in polling function @@ -184,8 +165,7 @@ func Test_Poller_Unsubscribe(t *testing.T) { } t.Run("Test multiple unsubscribe", func(t *testing.T) { - channel := make(chan Head, 1) - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) @@ -194,14 +174,12 @@ func Test_Poller_Unsubscribe(t *testing.T) { poller.Unsubscribe() }) - t.Run("Test unsubscribe with closed channel", func(t *testing.T) { - channel := make(chan Head, 1) - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + t.Run("Read channel after unsubscribe", func(t *testing.T) { + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) - <-channel - close(channel) poller.Unsubscribe() + require.Equal(t, <-channel, nil) }) } From 80590662bd9956d3c93449ca4703a2430e0613b7 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Mon, 6 May 2024 15:49:38 -0400 Subject: [PATCH 22/35] Normalize ref regex (#13112) --- .changeset/ten-dodos-run.md | 5 +++++ core/services/workflows/models_yaml.go | 2 +- .../testdata/fixtures/workflows/workflow_schema.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/ten-dodos-run.md diff --git a/.changeset/ten-dodos-run.md b/.changeset/ten-dodos-run.md new file mode 100644 index 00000000000..42ab8ec58b2 --- /dev/null +++ b/.changeset/ten-dodos-run.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Normalize keystone workflow ref regex property to match id regex diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 5ed7941f84a..74ed8ee466d 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -211,7 +211,7 @@ type stepDefinitionYaml struct { // - “ref” has a circular reference. // // NOTE: Should introduce a custom validator to cover trigger case - Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` + Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_-]+$"` // Capabilities can specify an additional optional ”inputs” property. It allows specifying a dependency on the result of one or more other capabilities. These are always runtime values that cannot be provided upfront. It takes a map of the argument name internal to the capability and an explicit reference to the values. // diff --git a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json index 7f257f7798d..f9f9fd88646 100644 --- a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json +++ b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json @@ -48,7 +48,7 @@ }, "ref": { "type": "string", - "pattern": "^[a-z0-9_]+$" + "pattern": "^[a-z0-9_-]+$" }, "inputs": { "$ref": "#/$defs/mapping" From c671a5c731b7028e36ecfac1b60b990f65d78fa2 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Mon, 6 May 2024 14:04:12 -0700 Subject: [PATCH 23/35] Revert "fix: ci-core print-races to slack conditionals (#13086)" (#13115) This reverts commit fbbadfb6a1ef746aff9a98178e6186e12f4a4f54. --- .github/workflows/ci-core.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index a3ea68380f9..1d7b58820b0 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -170,7 +170,7 @@ jobs: env: OUTPUT_FILE: ./output.txt USE_TEE: false - CL_DATABASE_URL: ${{ env.DB_URL }} + CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... - name: Print Filtered Test Results if: ${{ failure() && matrix.type.cmd == 'go_core_tests' && needs.filter.outputs.changes == 'true' }} @@ -203,7 +203,7 @@ jobs: ./coverage.txt ./postgres_logs.txt - name: Notify Slack - if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.base_ref == 'develop') && needs.filter.outputs.changes == 'true' }} + if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.event.branch == 'develop') && needs.filter.outputs.changes == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} From 7572a50a78a270188344786937f68233df82f65b Mon Sep 17 00:00:00 2001 From: FelixFan1992 Date: Mon, 6 May 2024 18:29:06 -0400 Subject: [PATCH 24/35] AUTO-10213 & AUTO-10214 & AUTO-10236: compare current gas price with user-defined max gas price in registry 2.1 pipeline (#12952) * AUTO-10213: pass an gas estimator to registry 2.1 pipeline * update tests and add changeset * update changeset * AUTO-10214: compare max gas price with current gas price in simulation process (#12955) * AUTO-10214: compare max gas price with current gas price in simulation process * refactor and add tests * linting (#12960) * linting * 2 * fix linting * create opts with latest block * AUTO-10236: add integration tests for max gas price check (#12974) * AUTO-10214: compare max gas price with current gas price in simulation process * refactor and add tests * linting (#12960) * linting * 2 * fix linting * AUTO-10236 * fix go mod * update test json * improve max gas price integration tests * AUTO-10214: compare max gas price with current gas price in simulation process * refactor and add tests * linting (#12960) * linting * 2 * fix linting * create opts with latest block * add some logs * fix bug and update logs * update * update * update logs * fix --- .changeset/funny-tips-promise.md | 6 + .changeset/neat-pianos-argue.md | 6 + .changeset/witty-weeks-kneel.md | 5 + .../evmregistry/v21/encoding/interface.go | 1 + .../evmregistry/v21/gasprice/gasprice.go | 70 ++++++++++ .../evmregistry/v21/gasprice/gasprice_test.go | 128 ++++++++++++++++++ .../ocr2keeper/evmregistry/v21/registry.go | 13 ++ .../v21/registry_check_pipeline.go | 16 ++- .../v21/registry_check_pipeline_test.go | 11 ++ .../contracts/ethereum_keeper_contracts.go | 41 ++++++ integration-tests/go.mod | 2 +- integration-tests/smoke/automation_test.go | 120 +++++++++++++++- .../smoke/automation_test.go_test_list.json | 4 + 13 files changed, 418 insertions(+), 5 deletions(-) create mode 100644 .changeset/funny-tips-promise.md create mode 100644 .changeset/neat-pianos-argue.md create mode 100644 .changeset/witty-weeks-kneel.md create mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go create mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go diff --git a/.changeset/funny-tips-promise.md b/.changeset/funny-tips-promise.md new file mode 100644 index 00000000000..16fd0a9fc33 --- /dev/null +++ b/.changeset/funny-tips-promise.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +#added +compare user-defined max gas price with current gas price in automation simulation pipeline diff --git a/.changeset/neat-pianos-argue.md b/.changeset/neat-pianos-argue.md new file mode 100644 index 00000000000..f65c19584db --- /dev/null +++ b/.changeset/neat-pianos-argue.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +#added +pass a gas estimator to registry 2.1 pipeline diff --git a/.changeset/witty-weeks-kneel.md b/.changeset/witty-weeks-kneel.md new file mode 100644 index 00000000000..d638d037081 --- /dev/null +++ b/.changeset/witty-weeks-kneel.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added an integration test for max gas price check diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go index e942078fe54..39d738fa7c6 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go @@ -31,6 +31,7 @@ const ( UpkeepFailureReasonInvalidRevertDataInput UpkeepFailureReason = 34 UpkeepFailureReasonSimulationFailed UpkeepFailureReason = 35 UpkeepFailureReasonTxHashReorged UpkeepFailureReason = 36 + UpkeepFailureReasonGasPriceTooHigh UpkeepFailureReason = 37 // pipeline execution error NoPipelineError PipelineExecutionState = 0 diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go new file mode 100644 index 00000000000..2c376443fa5 --- /dev/null +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go @@ -0,0 +1,70 @@ +package gasprice + +import ( + "context" + "math/big" + + "github.com/smartcontractkit/chainlink/v2/core/cbor" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" +) + +const ( + // feeLimit is a placeholder when getting current price from gas estimator. it does not impact gas price calculation + feeLimit = uint64(1_000_000) + // maxFeePrice is a placeholder when getting current price from gas estimator. it caps the returned gas price from + // the estimator. it's set to a very high value because the gas price will be compared with user-defined gas price + // later. + maxFeePrice = 1_000_000_000_000_000 +) + +type UpkeepOffchainConfig struct { + MaxGasPrice *big.Int `json:"maxGasPrice" cbor:"maxGasPrice"` +} + +// CheckGasPrice retrieves the current gas price and compare against the max gas price configured in upkeep's offchain config +// any errors in offchain config decoding will result in max gas price check disabled +func CheckGasPrice(ctx context.Context, upkeepId *big.Int, offchainConfigBytes []byte, ge gas.EvmFeeEstimator, lggr logger.Logger) encoding.UpkeepFailureReason { + if len(offchainConfigBytes) == 0 { + return encoding.UpkeepFailureReasonNone + } + + var offchainConfig UpkeepOffchainConfig + if err := cbor.ParseDietCBORToStruct(offchainConfigBytes, &offchainConfig); err != nil { + lggr.Errorw("failed to parse upkeep offchain config, gas price check is disabled", "upkeepId", upkeepId.String(), "err", err) + return encoding.UpkeepFailureReasonNone + } + if offchainConfig.MaxGasPrice == nil || offchainConfig.MaxGasPrice.Int64() <= 0 { + lggr.Warnw("maxGasPrice is not configured or incorrectly configured in upkeep offchain config, gas price check is disabled", "upkeepId", upkeepId.String()) + return encoding.UpkeepFailureReasonNone + } + lggr.Debugf("successfully decode offchain config for %s, max gas price is %s", upkeepId.String(), offchainConfig.MaxGasPrice.String()) + + fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice))) + if err != nil { + lggr.Errorw("failed to get fee, gas price check is disabled", "upkeepId", upkeepId.String(), "err", err) + return encoding.UpkeepFailureReasonNone + } + + if fee.ValidDynamic() { + lggr.Debugf("current gas price EIP-1559 is fee cap %s, tip cap %s", fee.DynamicFeeCap.String(), fee.DynamicTipCap.String()) + if fee.DynamicFeeCap.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { + // current gas price is higher than max gas price + lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.DynamicFeeCap.Int64()) + return encoding.UpkeepFailureReasonGasPriceTooHigh + } + lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.DynamicFeeCap.Int64()) + } else { + lggr.Debugf("current gas price legacy is %s", fee.Legacy.String()) + if fee.Legacy.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { + // current gas price is higher than max gas price + lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.Legacy.Int64()) + return encoding.UpkeepFailureReasonGasPriceTooHigh + } + lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.Legacy.Int64()) + } + + return encoding.UpkeepFailureReasonNone +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go new file mode 100644 index 00000000000..9b5640051df --- /dev/null +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go @@ -0,0 +1,128 @@ +package gasprice + +import ( + "math/big" + "testing" + + "github.com/fxamacker/cbor/v2" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + gasMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" +) + +type WrongOffchainConfig struct { + MaxGasPrice1 []int `json:"maxGasPrice1" cbor:"maxGasPrice1"` +} + +func TestGasPrice_Check(t *testing.T) { + lggr := logger.TestLogger(t) + uid, _ := new(big.Int).SetString("1843548457736589226156809205796175506139185429616502850435279853710366065936", 10) + + tests := []struct { + Name string + MaxGasPrice *big.Int + CurrentLegacyGasPrice *big.Int + CurrentDynamicGasPrice *big.Int + ExpectedResult encoding.UpkeepFailureReason + FailedToGetFee bool + NotConfigured bool + ParsingFailed bool + }{ + { + Name: "no offchain config", + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + { + Name: "maxGasPrice not configured in offchain config", + NotConfigured: true, + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + { + Name: "fail to parse offchain config", + ParsingFailed: true, + MaxGasPrice: big.NewInt(10_000_000_000), + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + { + Name: "fail to retrieve current gas price", + MaxGasPrice: big.NewInt(8_000_000_000), + FailedToGetFee: true, + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + { + Name: "current gas price is too high - legacy", + MaxGasPrice: big.NewInt(10_000_000_000), + CurrentLegacyGasPrice: big.NewInt(18_000_000_000), + ExpectedResult: encoding.UpkeepFailureReasonGasPriceTooHigh, + }, + { + Name: "current gas price is too high - dynamic", + MaxGasPrice: big.NewInt(10_000_000_000), + CurrentDynamicGasPrice: big.NewInt(15_000_000_000), + ExpectedResult: encoding.UpkeepFailureReasonGasPriceTooHigh, + }, + { + Name: "current gas price is less than user's max gas price - legacy", + MaxGasPrice: big.NewInt(8_000_000_000), + CurrentLegacyGasPrice: big.NewInt(5_000_000_000), + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + { + Name: "current gas price is less than user's max gas price - dynamic", + MaxGasPrice: big.NewInt(10_000_000_000), + CurrentDynamicGasPrice: big.NewInt(8_000_000_000), + ExpectedResult: encoding.UpkeepFailureReasonNone, + }, + } + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + ctx := testutils.Context(t) + ge := gasMocks.NewEvmFeeEstimator(t) + if test.FailedToGetFee { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + gas.EvmFee{}, + feeLimit, + errors.New("failed to retrieve gas price"), + ) + } else if test.CurrentLegacyGasPrice != nil { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + gas.EvmFee{ + Legacy: assets.NewWei(test.CurrentLegacyGasPrice), + }, + feeLimit, + nil, + ) + } else if test.CurrentDynamicGasPrice != nil { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + gas.EvmFee{ + DynamicFeeCap: assets.NewWei(test.CurrentDynamicGasPrice), + DynamicTipCap: assets.NewWei(big.NewInt(1_000_000_000)), + }, + feeLimit, + nil, + ) + } + + var oc []byte + if test.ParsingFailed { + oc, _ = cbor.Marshal(WrongOffchainConfig{MaxGasPrice1: []int{1, 2, 3}}) + if len(oc) > 0 { + oc[len(oc)-1] = 0x99 + } + } else if test.NotConfigured { + oc = []byte{1, 2, 3, 4} // parsing this will set maxGasPrice field to nil + } else if test.MaxGasPrice != nil { + oc, _ = cbor.Marshal(UpkeepOffchainConfig{MaxGasPrice: test.MaxGasPrice}) + } + fr := CheckGasPrice(ctx, uid, oc, ge, lggr) + assert.Equal(t, test.ExpectedResult, fr) + }) + } +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index 206932cf543..5a6466a8b15 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -27,6 +27,7 @@ import ( ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" @@ -113,6 +114,7 @@ func NewEvmRegistry( bs: blockSub, finalityDepth: finalityDepth, streams: streams.NewStreamsLookup(mercuryConfig, blockSub, client.Client(), registry, lggr), + ge: client.GasEstimator(), } } @@ -194,6 +196,7 @@ type EvmRegistry struct { logEventProvider logprovider.LogEventProvider finalityDepth uint32 streams streams.Lookup + ge gas.EvmFeeEstimator } func (r *EvmRegistry) Name() string { @@ -627,3 +630,13 @@ func (r *EvmRegistry) fetchTriggerConfig(id *big.Int) ([]byte, error) { } return cfg, nil } + +// fetchUpkeepOffchainConfig fetches upkeep offchain config in raw bytes for an upkeep. +func (r *EvmRegistry) fetchUpkeepOffchainConfig(id *big.Int) ([]byte, error) { + opts := r.buildCallOpts(r.ctx, nil) + ui, err := r.registry.GetUpkeep(opts, id) + if err != nil { + return []byte{}, err + } + return ui.OffchainConfig, nil +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go index 3e935d0adf1..e341730c794 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice" ) const ( @@ -305,7 +306,19 @@ func (r *EvmRegistry) simulatePerformUpkeeps(ctx context.Context, checkResults [ block, _, upkeepId := r.getBlockAndUpkeepId(cr.UpkeepID, cr.Trigger) - opts := r.buildCallOpts(ctx, block) + oc, err := r.fetchUpkeepOffchainConfig(upkeepId) + if err != nil { + // this is mostly caused by RPC flakiness + r.lggr.Errorw("failed get offchain config, gas price check will be disabled", "err", err, "upkeepId", upkeepId, "block", block) + } + fr := gasprice.CheckGasPrice(ctx, upkeepId, oc, r.ge, r.lggr) + if uint8(fr) == uint8(encoding.UpkeepFailureReasonGasPriceTooHigh) { + r.lggr.Infof("upkeep %s upkeep failure reason is %d", upkeepId, fr) + checkResults[i].Eligible = false + checkResults[i].Retryable = false + checkResults[i].IneligibilityReason = uint8(fr) + continue + } // Since checkUpkeep is true, simulate perform upkeep to ensure it doesn't revert payload, err := r.abi.Pack("simulatePerformUpkeep", upkeepId, cr.PerformData) @@ -317,6 +330,7 @@ func (r *EvmRegistry) simulatePerformUpkeeps(ctx context.Context, checkResults [ continue } + opts := r.buildCallOpts(ctx, block) var result string performReqs = append(performReqs, rpc.BatchElem{ Method: "eth_call", diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go index 330da44b71b..e74ad4821a6 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go @@ -23,6 +23,7 @@ import ( ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + gasMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" @@ -651,6 +652,13 @@ func TestRegistry_SimulatePerformUpkeeps(t *testing.T) { }).Once() e.client = client + mockReg := mocks.NewRegistry(t) + mockReg.On("GetUpkeep", mock.Anything, mock.Anything).Return( + encoding.UpkeepInfo{OffchainConfig: make([]byte, 0)}, + nil, + ).Times(2) + e.registry = mockReg + results, err := e.simulatePerformUpkeeps(testutils.Context(t), tc.inputs) assert.Equal(t, tc.results, results) assert.Equal(t, tc.err, err) @@ -670,6 +678,7 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry { mockReg := mocks.NewRegistry(t) mockHttpClient := mocks.NewHttpClient(t) client := evmClientMocks.NewClient(t) + ge := gasMocks.NewEvmFeeEstimator(t) r := &EvmRegistry{ lggr: lggr, @@ -694,6 +703,8 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry { AllowListCache: cache.New(defaultAllowListExpiration, cleanupInterval), }, hc: mockHttpClient, + bs: &BlockSubscriber{latestBlock: atomic.Pointer[ocr2keepers.BlockKey]{}}, + ge: ge, } return r } diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 337e3009f16..8ec6a547b55 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -87,6 +87,7 @@ type KeeperRegistry interface { UpdateCheckData(id *big.Int, newCheckData []byte) error SetUpkeepTriggerConfig(id *big.Int, triggerConfig []byte) error SetUpkeepPrivilegeConfig(id *big.Int, privilegeConfig []byte) error + SetUpkeepOffchainConfig(id *big.Int, offchainConfig []byte) error RegistryOwnerAddress() common.Address ChainModuleAddress() common.Address ReorgProtectionEnabled() bool @@ -1225,6 +1226,46 @@ func (v *EthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { } } +func (v *EthereumKeeperRegistry) 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 *EthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*UpkeepPerformedLog, error) { switch v.version { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index babf82a7d96..d8210ccc123 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -9,6 +9,7 @@ require ( github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df 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 github.com/go-resty/resty/v2 v2.7.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 @@ -174,7 +175,6 @@ require ( github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fvbommel/sortorder v1.0.2 // indirect - github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/solana-go v1.8.4 // indirect diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 81d18139122..ee9541926df 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -11,6 +11,8 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/fxamacker/cbor/v2" "github.com/onsi/gomega" "github.com/stretchr/testify/require" @@ -34,6 +36,7 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" ) @@ -190,7 +193,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool, automationTestConfig t for i := 0; i < len(upkeepIDs); i++ { counter, err := consumers[i].Counter(testcontext.Get(t)) require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep index", i).Msg("Number of upkeeps performed") g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) } @@ -631,7 +634,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { "Expected consumer counter to be greater than 0, but got %d", counter.Int64()) l.Info(). Int64("Upkeep counter", counter.Int64()). - Int64("Upkeep ID", int64(i)). + Int64("Upkeep index", int64(i)). Msg("Number of upkeeps performed") } }, "4m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer @@ -657,7 +660,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") l.Info(). - Int64("Upkeep ID", int64(i)). + Int64("Upkeep index", int64(i)). Int64("Upkeep counter", currentCounter.Int64()). Int64("initial counter", initialCounters[i].Int64()). Msg("Number of upkeeps performed") @@ -1120,6 +1123,117 @@ func TestUpdateCheckData(t *testing.T) { } } +func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { + t.Parallel() + registryVersions := map[string]ethereum.KeeperRegistryVersion{ + // registry20 also has upkeep offchain config but the max gas price check is not implemented + "registry_2_1": ethereum.RegistryVersion_2_1, + "registry_2_2": ethereum.RegistryVersion_2_2, + } + + for n, rv := range registryVersions { + name := n + registryVersion := rv + t.Run(name, func(t *testing.T) { + t.Parallel() + l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } + a := setupAutomationTestDocker( + t, registryVersion, automationDefaultRegistryConfig(config), false, false, &config, + ) + + consumers, upkeepIDs := actions.DeployConsumers( + t, + a.Registry, + a.Registrar, + a.LinkToken, + a.Deployer, + a.ChainClient, + defaultAmountOfUpkeeps, + big.NewInt(automationDefaultLinkFunds), + automationDefaultUpkeepGasLimit, + false, + false, + ) + gom := gomega.NewGomegaWithT(t) + + l.Info().Msg("waiting for all upkeeps to be performed at least once") + gom.Eventually(func(g gomega.Gomega) { + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(testcontext.Get(t)) + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), + "Expected consumer counter to be greater than 0, but got %d") + } + }, "3m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer + + // set the maxGasPrice to 1 wei + uoc, _ := cbor.Marshal(gasprice.UpkeepOffchainConfig{MaxGasPrice: big.NewInt(1)}) + l.Info().Msgf("setting all upkeeps' offchain config to %s, which means maxGasPrice is 1 wei", hexutil.Encode(uoc)) + for _, uid := range upkeepIDs { + err = a.Registry.SetUpkeepOffchainConfig(uid, uoc) + require.NoError(t, err, "Error setting upkeep offchain config") + err = a.ChainClient.WaitForEvents() + require.NoError(t, err, "Error waiting for events from setting upkeep offchain config") + } + + // Store how many times each upkeep performed once their offchain config is set with maxGasPrice = 1 wei + var countersAfterSettingLowMaxGasPrice = make([]*big.Int, len(upkeepIDs)) + for i := 0; i < len(upkeepIDs); i++ { + countersAfterSettingLowMaxGasPrice[i], err = consumers[i].Counter(testcontext.Get(t)) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + l.Info().Int64("Upkeep Performed times", countersAfterSettingLowMaxGasPrice[i].Int64()).Int("Upkeep index", i).Msg("Number of upkeeps performed") + } + + var latestCounter *big.Int + // the counters of all the upkeeps should stay constant because they are no longer getting serviced + gom.Consistently(func(g gomega.Gomega) { + for i := 0; i < len(upkeepIDs); i++ { + latestCounter, err = consumers[i].Counter(testcontext.Get(t)) + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) + g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterSettingLowMaxGasPrice[i].Int64()), + "Expected consumer counter to remain constant at %d, but got %d", + countersAfterSettingLowMaxGasPrice[i].Int64(), latestCounter.Int64()) + } + }, "2m", "1s").Should(gomega.Succeed()) + l.Info().Msg("no upkeeps is performed because their max gas price is only 1 wei") + + // setting offchain config with a high max gas price for the first upkeep, it should perform again while + // other upkeeps should not perform + // set the maxGasPrice to 500 gwei for the first upkeep + uoc, _ = cbor.Marshal(gasprice.UpkeepOffchainConfig{MaxGasPrice: big.NewInt(500_000_000_000)}) + l.Info().Msgf("setting the first upkeeps' offchain config to %s, which means maxGasPrice is 500 gwei", hexutil.Encode(uoc)) + err = a.Registry.SetUpkeepOffchainConfig(upkeepIDs[0], uoc) + require.NoError(t, err, "Error setting upkeep offchain config") + + // the counters of all other upkeeps should stay constant because their max gas price remains very low + gom.Consistently(func(g gomega.Gomega) { + for i := 1; i < len(upkeepIDs); i++ { + latestCounter, err = consumers[i].Counter(testcontext.Get(t)) + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) + g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterSettingLowMaxGasPrice[i].Int64()), + "Expected consumer counter to remain constant at %d, but got %d", + countersAfterSettingLowMaxGasPrice[i].Int64(), latestCounter.Int64()) + } + }, "2m", "1s").Should(gomega.Succeed()) + l.Info().Msg("all the rest upkeeps did not perform again because their max gas price remains 1 wei") + + // the first upkeep should start performing again + gom.Eventually(func(g gomega.Gomega) { + latestCounter, err = consumers[0].Counter(testcontext.Get(t)) + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index 0") + g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically(">", countersAfterSettingLowMaxGasPrice[0].Int64()), + "Expected consumer counter to be greater than %d, but got %d", + countersAfterSettingLowMaxGasPrice[0].Int64(), latestCounter.Int64()) + }, "2m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer + l.Info().Int64("Upkeep Performed times", latestCounter.Int64()).Msg("the first upkeep performed again") + }) + } +} + func setupAutomationTestDocker( t *testing.T, registryVersion ethereum.KeeperRegistryVersion, diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json index 03029c9018b..e8f0f838dfd 100644 --- a/integration-tests/smoke/automation_test.go_test_list.json +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -70,6 +70,10 @@ { "name": "TestUpdateCheckData", "nodes": 3 + }, + { + "name": "TestSetOffchainConfigWithMaxGasPrice", + "nodes": 2 } ] } \ No newline at end of file From ac893364e6c6ede08e9bf04da7dc64e0da94ab6e Mon Sep 17 00:00:00 2001 From: Chunkai Yang Date: Tue, 7 May 2024 01:21:07 -0400 Subject: [PATCH 25/35] Feature ORM for CCIP in-db prices (#12813) * define CCIP migration sql * POC orm * use context as opposed to pg opts * add CCIP ORM test * pass ORM tests * add change set * update changeset * fix lint and goimports * address comments * replce big.int with assets.wei for scanner/valuer type * inline table names * use named exec to insert multiple rows * bump migration index --- .changeset/mighty-flies-breathe.md | 5 + core/services/ccip/mocks/orm.go | 164 +++++++++ core/services/ccip/orm.go | 163 +++++++++ core/services/ccip/orm_test.go | 346 ++++++++++++++++++ .../migrations/0236_ccip_prices_cache.sql | 36 ++ 5 files changed, 714 insertions(+) create mode 100644 .changeset/mighty-flies-breathe.md create mode 100644 core/services/ccip/mocks/orm.go create mode 100644 core/services/ccip/orm.go create mode 100644 core/services/ccip/orm_test.go create mode 100644 core/store/migrate/migrations/0236_ccip_prices_cache.sql diff --git a/.changeset/mighty-flies-breathe.md b/.changeset/mighty-flies-breathe.md new file mode 100644 index 00000000000..d983aad7086 --- /dev/null +++ b/.changeset/mighty-flies-breathe.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added ORM and corresponding tables for CCIP gas prices and token prices diff --git a/core/services/ccip/mocks/orm.go b/core/services/ccip/mocks/orm.go new file mode 100644 index 00000000000..b9afc6c8695 --- /dev/null +++ b/core/services/ccip/mocks/orm.go @@ -0,0 +1,164 @@ +// Code generated by mockery v2.42.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + ccip "github.com/smartcontractkit/chainlink/v2/core/services/ccip" + + mock "github.com/stretchr/testify/mock" + + time "time" +) + +// ORM is an autogenerated mock type for the ORM type +type ORM struct { + mock.Mock +} + +// ClearGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, to +func (_m *ORM) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { + ret := _m.Called(ctx, destChainSelector, to) + + if len(ret) == 0 { + panic("no return value specified for ClearGasPricesByDestChain") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, time.Time) error); ok { + r0 = rf(ctx, destChainSelector, to) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ClearTokenPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, to +func (_m *ORM) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { + ret := _m.Called(ctx, destChainSelector, to) + + if len(ret) == 0 { + panic("no return value specified for ClearTokenPricesByDestChain") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, time.Time) error); ok { + r0 = rf(ctx, destChainSelector, to) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector +func (_m *ORM) GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]ccip.GasPrice, error) { + ret := _m.Called(ctx, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetGasPricesByDestChain") + } + + var r0 []ccip.GasPrice + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]ccip.GasPrice, error)); ok { + return rf(ctx, destChainSelector) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []ccip.GasPrice); ok { + r0 = rf(ctx, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ccip.GasPrice) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTokenPricesByDestChain provides a mock function with given fields: ctx, destChainSelector +func (_m *ORM) GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]ccip.TokenPrice, error) { + ret := _m.Called(ctx, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPricesByDestChain") + } + + var r0 []ccip.TokenPrice + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]ccip.TokenPrice, error)); ok { + return rf(ctx, destChainSelector) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []ccip.TokenPrice); ok { + r0 = rf(ctx, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ccip.TokenPrice) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// InsertGasPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, jobId, gasPrices +func (_m *ORM) InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []ccip.GasPriceUpdate) error { + ret := _m.Called(ctx, destChainSelector, jobId, gasPrices) + + if len(ret) == 0 { + panic("no return value specified for InsertGasPricesForDestChain") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, int32, []ccip.GasPriceUpdate) error); ok { + r0 = rf(ctx, destChainSelector, jobId, gasPrices) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// InsertTokenPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, jobId, tokenPrices +func (_m *ORM) InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []ccip.TokenPriceUpdate) error { + ret := _m.Called(ctx, destChainSelector, jobId, tokenPrices) + + if len(ret) == 0 { + panic("no return value specified for InsertTokenPricesForDestChain") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, int32, []ccip.TokenPriceUpdate) error); ok { + r0 = rf(ctx, destChainSelector, jobId, tokenPrices) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewORM creates a new instance of ORM. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewORM(t interface { + mock.TestingT + Cleanup(func()) +}) *ORM { + mock := &ORM{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ccip/orm.go b/core/services/ccip/orm.go new file mode 100644 index 00000000000..8af7762b18d --- /dev/null +++ b/core/services/ccip/orm.go @@ -0,0 +1,163 @@ +package ccip + +import ( + "context" + "fmt" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" +) + +type GasPrice struct { + SourceChainSelector uint64 + GasPrice *assets.Wei + CreatedAt time.Time +} + +type GasPriceUpdate struct { + SourceChainSelector uint64 + GasPrice *assets.Wei +} + +type TokenPrice struct { + TokenAddr string + TokenPrice *assets.Wei + CreatedAt time.Time +} + +type TokenPriceUpdate struct { + TokenAddr string + TokenPrice *assets.Wei +} + +//go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore +type ORM interface { + GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]GasPrice, error) + GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]TokenPrice, error) + + InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []GasPriceUpdate) error + InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []TokenPriceUpdate) error + + ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error + ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error +} + +type orm struct { + ds sqlutil.DataSource +} + +var _ ORM = (*orm)(nil) + +func NewORM(ds sqlutil.DataSource) (ORM, error) { + if ds == nil { + return nil, fmt.Errorf("datasource to CCIP NewORM cannot be nil") + } + + return &orm{ + ds: ds, + }, nil +} + +func (o *orm) GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]GasPrice, error) { + var gasPrices []GasPrice + stmt := ` + SELECT DISTINCT ON (source_chain_selector) + source_chain_selector, gas_price, created_at + FROM ccip.observed_gas_prices + WHERE chain_selector = $1 + ORDER BY source_chain_selector, created_at DESC; + ` + err := o.ds.SelectContext(ctx, &gasPrices, stmt, destChainSelector) + if err != nil { + return nil, err + } + + return gasPrices, nil +} + +func (o *orm) GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]TokenPrice, error) { + var tokenPrices []TokenPrice + stmt := ` + SELECT DISTINCT ON (token_addr) + token_addr, token_price, created_at + FROM ccip.observed_token_prices + WHERE chain_selector = $1 + ORDER BY token_addr, created_at DESC; + ` + err := o.ds.SelectContext(ctx, &tokenPrices, stmt, destChainSelector) + if err != nil { + return nil, err + } + + return tokenPrices, nil +} + +func (o *orm) InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []GasPriceUpdate) error { + if len(gasPrices) == 0 { + return nil + } + + now := time.Now() + insertData := make([]map[string]interface{}, 0, len(gasPrices)) + for _, price := range gasPrices { + insertData = append(insertData, map[string]interface{}{ + "chain_selector": destChainSelector, + "job_id": jobId, + "source_chain_selector": price.SourceChainSelector, + "gas_price": price.GasPrice, + "created_at": now, + }) + } + + stmt := `INSERT INTO ccip.observed_gas_prices (chain_selector, job_id, source_chain_selector, gas_price, created_at) + VALUES (:chain_selector, :job_id, :source_chain_selector, :gas_price, :created_at);` + _, err := o.ds.NamedExecContext(ctx, stmt, insertData) + if err != nil { + err = fmt.Errorf("error inserting gas prices for job %d: %w", jobId, err) + } + + return err +} + +func (o *orm) InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []TokenPriceUpdate) error { + if len(tokenPrices) == 0 { + return nil + } + + now := time.Now() + insertData := make([]map[string]interface{}, 0, len(tokenPrices)) + for _, price := range tokenPrices { + insertData = append(insertData, map[string]interface{}{ + "chain_selector": destChainSelector, + "job_id": jobId, + "token_addr": price.TokenAddr, + "token_price": price.TokenPrice, + "created_at": now, + }) + } + + stmt := `INSERT INTO ccip.observed_token_prices (chain_selector, job_id, token_addr, token_price, created_at) + VALUES (:chain_selector, :job_id, :token_addr, :token_price, :created_at);` + _, err := o.ds.NamedExecContext(ctx, stmt, insertData) + if err != nil { + err = fmt.Errorf("error inserting token prices for job %d: %w", jobId, err) + } + + return err +} + +func (o *orm) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { + stmt := `DELETE FROM ccip.observed_gas_prices WHERE chain_selector = $1 AND created_at < $2` + + _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, to) + return err +} + +func (o *orm) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { + stmt := `DELETE FROM ccip.observed_token_prices WHERE chain_selector = $1 AND created_at < $2` + + _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, to) + return err +} diff --git a/core/services/ccip/orm_test.go b/core/services/ccip/orm_test.go new file mode 100644 index 00000000000..741cf4b5b38 --- /dev/null +++ b/core/services/ccip/orm_test.go @@ -0,0 +1,346 @@ +package ccip + +import ( + "math/big" + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" +) + +func setupORM(t *testing.T) (ORM, sqlutil.DataSource) { + t.Helper() + + db := pgtest.NewSqlxDB(t) + orm, err := NewORM(db) + + require.NoError(t, err) + + return orm, db +} + +func generateChainSelectors(n int) []uint64 { + selectors := make([]uint64, n) + for i := 0; i < n; i++ { + selectors[i] = rand.Uint64() + } + + return selectors +} + +func generateGasPriceUpdates(chainSelector uint64, n int) []GasPriceUpdate { + updates := make([]GasPriceUpdate, n) + for i := 0; i < n; i++ { + // gas prices can take up whole range of uint256 + uint256Max := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)) + row := GasPriceUpdate{ + SourceChainSelector: chainSelector, + GasPrice: assets.NewWei(new(big.Int).Sub(uint256Max, big.NewInt(int64(i)))), + } + updates[i] = row + } + + return updates +} + +func generateTokenAddresses(n int) []string { + addrs := make([]string, n) + for i := 0; i < n; i++ { + addrs[i] = utils.RandomAddress().Hex() + } + + return addrs +} + +func generateTokenPriceUpdates(tokenAddr string, n int) []TokenPriceUpdate { + updates := make([]TokenPriceUpdate, n) + for i := 0; i < n; i++ { + row := TokenPriceUpdate{ + TokenAddr: tokenAddr, + TokenPrice: assets.NewWei(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(int64(i)))), + } + updates[i] = row + } + + return updates +} + +func getGasTableRowCount(t *testing.T, ds sqlutil.DataSource) int { + var count int + stmt := `SELECT COUNT(*) FROM ccip.observed_gas_prices;` + err := ds.QueryRowxContext(testutils.Context(t), stmt).Scan(&count) + require.NoError(t, err) + + return count +} + +func getTokenTableRowCount(t *testing.T, ds sqlutil.DataSource) int { + var count int + stmt := `SELECT COUNT(*) FROM ccip.observed_token_prices;` + err := ds.QueryRowxContext(testutils.Context(t), stmt).Scan(&count) + require.NoError(t, err) + + return count +} + +func TestInitORM(t *testing.T) { + t.Parallel() + + orm, _ := setupORM(t) + assert.NotNil(t, orm) +} + +func TestORM_EmptyGasPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, _ := setupORM(t) + + prices, err := orm.GetGasPricesByDestChain(ctx, 1) + assert.Equal(t, 0, len(prices)) + assert.NoError(t, err) +} + +func TestORM_EmptyTokenPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, _ := setupORM(t) + + prices, err := orm.GetTokenPricesByDestChain(ctx, 1) + assert.Equal(t, 0, len(prices)) + assert.NoError(t, err) +} + +func TestORM_InsertAndGetGasPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, db := setupORM(t) + + numJobs := 5 + numSourceChainSelectors := 10 + numUpdatesPerSourceSelector := 20 + destSelector := uint64(1) + + sourceSelectors := generateChainSelectors(numSourceChainSelectors) + + updates := make(map[uint64][]GasPriceUpdate) + for _, selector := range sourceSelectors { + updates[selector] = generateGasPriceUpdates(selector, numUpdatesPerSourceSelector) + } + + // 5 jobs, each inserting prices for 10 chains, with 20 updates per chain. + expectedPrices := make(map[uint64]GasPriceUpdate) + for i := 0; i < numJobs; i++ { + for selector, updatesPerSelector := range updates { + lastIndex := len(updatesPerSelector) - 1 + + err := orm.InsertGasPricesForDestChain(ctx, destSelector, int32(i), updatesPerSelector[:lastIndex]) + assert.NoError(t, err) + err = orm.InsertGasPricesForDestChain(ctx, destSelector, int32(i), updatesPerSelector[lastIndex:]) + assert.NoError(t, err) + + expectedPrices[selector] = updatesPerSelector[lastIndex] + } + } + + // verify number of rows inserted + numRows := getGasTableRowCount(t, db) + assert.Equal(t, numJobs*numSourceChainSelectors*numUpdatesPerSourceSelector, numRows) + + prices, err := orm.GetGasPricesByDestChain(ctx, destSelector) + assert.NoError(t, err) + // should return 1 price per source chain selector + assert.Equal(t, numSourceChainSelectors, len(prices)) + + // verify getGasPrices returns prices of latest timestamp + for _, price := range prices { + selector := price.SourceChainSelector + assert.Equal(t, expectedPrices[selector].GasPrice, price.GasPrice) + } + + // after the initial inserts, insert new round of prices, 1 price per selector this time + var combinedUpdates []GasPriceUpdate + for selector, updatesPerSelector := range updates { + combinedUpdates = append(combinedUpdates, updatesPerSelector[0]) + expectedPrices[selector] = updatesPerSelector[0] + } + + err = orm.InsertGasPricesForDestChain(ctx, destSelector, 1, combinedUpdates) + assert.NoError(t, err) + assert.Equal(t, numJobs*numSourceChainSelectors*numUpdatesPerSourceSelector+numSourceChainSelectors, getGasTableRowCount(t, db)) + + prices, err = orm.GetGasPricesByDestChain(ctx, destSelector) + assert.NoError(t, err) + assert.Equal(t, numSourceChainSelectors, len(prices)) + + for _, price := range prices { + selector := price.SourceChainSelector + assert.Equal(t, expectedPrices[selector].GasPrice, price.GasPrice) + } +} + +func TestORM_InsertAndDeleteGasPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, db := setupORM(t) + + numSourceChainSelectors := 10 + numUpdatesPerSourceSelector := 20 + destSelector := uint64(1) + + sourceSelectors := generateChainSelectors(numSourceChainSelectors) + + updates := make(map[uint64][]GasPriceUpdate) + for _, selector := range sourceSelectors { + updates[selector] = generateGasPriceUpdates(selector, numUpdatesPerSourceSelector) + } + + for _, updatesPerSelector := range updates { + err := orm.InsertGasPricesForDestChain(ctx, destSelector, 1, updatesPerSelector) + assert.NoError(t, err) + } + + interimTimeStamp := time.Now() + + // insert for the 2nd time after interimTimeStamp + for _, updatesPerSelector := range updates { + err := orm.InsertGasPricesForDestChain(ctx, destSelector, 1, updatesPerSelector) + assert.NoError(t, err) + } + + assert.Equal(t, 2*numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) + + // clear by interimTimeStamp should delete rows inserted before it + err := orm.ClearGasPricesByDestChain(ctx, destSelector, interimTimeStamp) + assert.NoError(t, err) + assert.Equal(t, numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) + + // clear by Now() should delete all rows + err = orm.ClearGasPricesByDestChain(ctx, destSelector, time.Now()) + assert.NoError(t, err) + assert.Equal(t, 0, getGasTableRowCount(t, db)) +} + +func TestORM_InsertAndGetTokenPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, db := setupORM(t) + + numJobs := 5 + numAddresses := 10 + numUpdatesPerAddress := 20 + destSelector := uint64(1) + + addrs := generateTokenAddresses(numAddresses) + + updates := make(map[string][]TokenPriceUpdate) + for _, addr := range addrs { + updates[addr] = generateTokenPriceUpdates(addr, numUpdatesPerAddress) + } + + // 5 jobs, each inserting prices for 10 chains, with 20 updates per chain. + expectedPrices := make(map[string]TokenPriceUpdate) + for i := 0; i < numJobs; i++ { + for addr, updatesPerAddr := range updates { + lastIndex := len(updatesPerAddr) - 1 + + err := orm.InsertTokenPricesForDestChain(ctx, destSelector, int32(i), updatesPerAddr[:lastIndex]) + assert.NoError(t, err) + err = orm.InsertTokenPricesForDestChain(ctx, destSelector, int32(i), updatesPerAddr[lastIndex:]) + assert.NoError(t, err) + + expectedPrices[addr] = updatesPerAddr[lastIndex] + } + } + + // verify number of rows inserted + numRows := getTokenTableRowCount(t, db) + assert.Equal(t, numJobs*numAddresses*numUpdatesPerAddress, numRows) + + prices, err := orm.GetTokenPricesByDestChain(ctx, destSelector) + assert.NoError(t, err) + // should return 1 price per source chain selector + assert.Equal(t, numAddresses, len(prices)) + + // verify getTokenPrices returns prices of latest timestamp + for _, price := range prices { + addr := price.TokenAddr + assert.Equal(t, expectedPrices[addr].TokenPrice, price.TokenPrice) + } + + // after the initial inserts, insert new round of prices, 1 price per selector this time + var combinedUpdates []TokenPriceUpdate + for addr, updatesPerAddr := range updates { + combinedUpdates = append(combinedUpdates, updatesPerAddr[0]) + expectedPrices[addr] = updatesPerAddr[0] + } + + err = orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, combinedUpdates) + assert.NoError(t, err) + assert.Equal(t, numJobs*numAddresses*numUpdatesPerAddress+numAddresses, getTokenTableRowCount(t, db)) + + prices, err = orm.GetTokenPricesByDestChain(ctx, destSelector) + assert.NoError(t, err) + assert.Equal(t, numAddresses, len(prices)) + + for _, price := range prices { + addr := price.TokenAddr + assert.Equal(t, expectedPrices[addr].TokenPrice, price.TokenPrice) + } +} + +func TestORM_InsertAndDeleteTokenPrices(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + orm, db := setupORM(t) + + numAddresses := 10 + numUpdatesPerAddress := 20 + destSelector := uint64(1) + + addrs := generateTokenAddresses(numAddresses) + + updates := make(map[string][]TokenPriceUpdate) + for _, addr := range addrs { + updates[addr] = generateTokenPriceUpdates(addr, numUpdatesPerAddress) + } + + for _, updatesPerAddr := range updates { + err := orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, updatesPerAddr) + assert.NoError(t, err) + } + + interimTimeStamp := time.Now() + + // insert for the 2nd time after interimTimeStamp + for _, updatesPerAddr := range updates { + err := orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, updatesPerAddr) + assert.NoError(t, err) + } + + assert.Equal(t, 2*numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) + + // clear by interimTimeStamp should delete rows inserted before it + err := orm.ClearTokenPricesByDestChain(ctx, destSelector, interimTimeStamp) + assert.NoError(t, err) + assert.Equal(t, numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) + + // clear by Now() should delete all rows + err = orm.ClearTokenPricesByDestChain(ctx, destSelector, time.Now()) + assert.NoError(t, err) + assert.Equal(t, 0, getTokenTableRowCount(t, db)) +} diff --git a/core/store/migrate/migrations/0236_ccip_prices_cache.sql b/core/store/migrate/migrations/0236_ccip_prices_cache.sql new file mode 100644 index 00000000000..e88b68e5575 --- /dev/null +++ b/core/store/migrate/migrations/0236_ccip_prices_cache.sql @@ -0,0 +1,36 @@ +-- +goose Up +-- +goose StatementBegin +CREATE SCHEMA ccip; + +CREATE TABLE ccip.observed_gas_prices( + chain_selector NUMERIC(20,0) NOT NULL, + job_id INTEGER NOT NULL, + source_chain_selector NUMERIC(20,0) NOT NULL, + gas_price NUMERIC(78,0) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE TABLE ccip.observed_token_prices( + chain_selector NUMERIC(20,0) NOT NULL, + job_id INTEGER NOT NULL, + token_addr BYTEA NOT NULL, + token_price NUMERIC(78,0) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX idx_ccip_gas_prices_chain_gas_price_timestamp ON ccip.observed_gas_prices (chain_selector, source_chain_selector, created_at DESC); +CREATE INDEX idx_ccip_token_prices_token_price_timestamp ON ccip.observed_token_prices (chain_selector, token_addr, created_at DESC); + +-- +goose StatementEnd + + +-- +goose Down +-- +goose StatementBegin +DROP INDEX IF EXISTS idx_ccip_token_prices_token_value; +DROP INDEX IF EXISTS idx_ccip_gas_prices_chain_value; + +DROP TABLE ccip.observed_token_prices; +DROP TABLE ccip.observed_gas_prices; + +DROP SCHEMA ccip; +-- +goose StatementEnd From e407400aab0850ce36ab26079cd24212764838e1 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 7 May 2024 05:03:45 -0500 Subject: [PATCH 26/35] golangci-lint: add whitespace (#13030) --- .golangci.yml | 1 + common/client/multi_node.go | 3 --- common/client/multi_node_test.go | 3 --- common/client/node_fsm_test.go | 1 - common/client/node_lifecycle.go | 2 -- common/client/node_lifecycle_test.go | 9 --------- common/internal/utils/utils.go | 1 - common/txmgr/broadcaster.go | 1 - common/txmgr/confirmer.go | 3 --- core/capabilities/registry.go | 1 - core/capabilities/targets/write_target_test.go | 1 - core/chains/evm/assets/wei.go | 2 -- core/chains/evm/client/client_test.go | 2 -- core/chains/evm/client/errors_test.go | 1 - core/chains/evm/client/helpers_test.go | 2 -- core/chains/evm/client/node.go | 2 -- core/chains/evm/client/node_lifecycle_test.go | 1 - core/chains/evm/client/pool_test.go | 1 - core/chains/evm/client/sub_error_wrapper_test.go | 1 - core/chains/evm/forwarders/forwarder_manager.go | 1 - core/chains/evm/gas/block_history_estimator_test.go | 2 -- core/chains/evm/gas/fixed_price_estimator.go | 1 - core/chains/evm/headtracker/head_saver_test.go | 1 - core/chains/evm/headtracker/heads_test.go | 2 -- core/chains/evm/log/eth_subscriber.go | 2 -- core/chains/evm/log/helpers_test.go | 3 --- core/chains/evm/log/integration_test.go | 1 - core/chains/evm/log/registrations.go | 2 -- core/chains/evm/logpoller/log_poller_internal_test.go | 1 - core/chains/evm/logpoller/log_poller_test.go | 2 -- core/chains/evm/logpoller/orm.go | 1 - core/chains/evm/logpoller/orm_test.go | 1 - core/chains/evm/monitor/balance.go | 1 - core/chains/evm/testutils/config_test.go | 1 - core/chains/evm/txmgr/attempts.go | 1 - core/chains/evm/txmgr/broadcaster_test.go | 2 -- core/chains/evm/txmgr/confirmer_test.go | 6 ------ core/chains/evm/txmgr/evm_tx_store.go | 2 -- core/chains/evm/txmgr/evm_tx_store_test.go | 1 - core/chains/evm/txmgr/nonce_tracker.go | 1 - core/chains/evm/txmgr/nonce_tracker_test.go | 4 ---- core/chains/evm/txmgr/transmitchecker.go | 1 - core/chains/evm/types/address.go | 1 - core/chains/evm/types/block_json_benchmark_test.go | 1 - core/chains/evm/types/head_test.go | 1 - core/chains/evm/types/models.go | 3 --- core/chains/evm/types/models_test.go | 2 -- core/chains/evm/utils/ethabi_test.go | 3 --- core/chains/evm/utils/utils.go | 1 - core/chains/legacyevm/chain_test.go | 1 - core/cmd/app.go | 1 - core/cmd/cosmos_keys_commands_test.go | 1 - core/cmd/evm_transaction_commands_test.go | 1 - core/cmd/ocr2_keys_commands_test.go | 1 - core/cmd/shell.go | 1 - core/cmd/shell_local_test.go | 2 -- core/cmd/shell_remote_test.go | 2 -- core/cmd/shell_test.go | 4 ---- core/cmd/solana_keys_commands_test.go | 1 - core/cmd/starknet_keys_commands_test.go | 1 - core/config/toml/types.go | 3 --- core/gethwrappers/versions.go | 1 - core/internal/cltest/cltest.go | 3 --- core/internal/cltest/mocks.go | 1 - core/internal/testutils/evmtest/evmtest.go | 1 - core/logger/audit/audit_logger.go | 1 - core/scripts/chaincli/handler/keeper.go | 1 - core/scripts/chaincli/handler/ocr2_config.go | 1 - core/scripts/chaincli/handler/report.go | 3 --- core/scripts/common/helpers.go | 3 --- core/scripts/common/helpers_test.go | 1 - core/scripts/common/vrf/setup-envs/main.go | 2 -- core/scripts/functions/src/fetch_keys.go | 1 - core/scripts/functions/src/files_test.go | 1 - core/scripts/ocr2vrf/setup_ocr2vrf.go | 1 - core/scripts/vrfv2plus/testnet/proofs.go | 1 - core/services/blockhashstore/delegate.go | 3 --- core/services/blockheaderfeeder/delegate.go | 3 --- core/services/chainlink/config_general_test.go | 1 - core/services/chainlink/config_p2p.go | 1 - core/services/chainlink/config_pyroscope_test.go | 1 - core/services/chainlink/config_web_server_test.go | 1 - core/services/chainlink/relayer_chain_interoperators.go | 3 --- .../chainlink/relayer_chain_interoperators_test.go | 5 ----- core/services/chainlink/relayer_factory.go | 6 ------ core/services/feeds/service.go | 2 -- core/services/fluxmonitorv2/flux_monitor.go | 1 - core/services/fluxmonitorv2/integrations_test.go | 1 - core/services/fluxmonitorv2/orm.go | 1 - core/services/fluxmonitorv2/poll_manager.go | 1 - core/services/fluxmonitorv2/poll_manager_test.go | 1 - core/services/functions/connector_handler_test.go | 7 ------- core/services/functions/external_adapter_client_test.go | 1 - core/services/functions/orm_test.go | 1 - .../handlers/functions/allowlist/allowlist_test.go | 2 -- core/services/job/kv_orm.go | 1 - core/services/job/models.go | 1 - core/services/job/orm.go | 1 - core/services/job/runner_integration_test.go | 1 - core/services/job/spawner.go | 2 -- core/services/keeper/validate_test.go | 1 - core/services/keystore/eth_test.go | 1 - core/services/keystore/keys/exportutils.go | 2 -- core/services/keystore/keys/vrfkey/public_key_test.go | 1 - core/services/keystore/models_test.go | 1 - core/services/keystore/ocr2_test.go | 1 - core/services/keystore/starknet.go | 1 - core/services/keystore/starknet_test.go | 1 - core/services/llo/orm_test.go | 1 - core/services/nurse.go | 2 -- core/services/nurse_test.go | 1 - core/services/ocr/config_overrider.go | 1 - core/services/ocr2/delegate.go | 1 - core/services/ocr2/delegate_test.go | 1 - core/services/ocr2/plugins/generic/relayerset.go | 3 --- core/services/ocr2/plugins/generic/relayerset_test.go | 2 -- core/services/ocr2/plugins/llo/config/config.go | 1 - core/services/ocr2/plugins/mercury/config/config_test.go | 1 - .../ocr2/plugins/ocr2keeper/evmregistry/v20/abi_test.go | 1 - .../plugins/ocr2keeper/evmregistry/v20/encoder_test.go | 1 - .../ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go | 1 - .../evmregistry/v21/logprovider/integration_test.go | 1 - .../ocr2keeper/evmregistry/v21/logprovider/provider.go | 1 - .../evmregistry/v21/logprovider/provider_test.go | 1 - .../ocr2/plugins/ocr2keeper/evmregistry/v21/services.go | 1 - .../services/ocr2/plugins/ocr2keeper/integration_test.go | 1 - .../ocr2/plugins/ocr2vrf/coordinator/coordinator.go | 4 ---- .../ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go | 1 - .../ocr2/plugins/ocr2vrf/coordinator/ocr_cache.go | 4 ---- .../ocr2/plugins/ocr2vrf/coordinator/ocr_cache_test.go | 3 --- .../plugins/ocr2vrf/internal/ocr2vrf_integration_test.go | 1 - .../ocr2vrf/reportserializer/report_serializer.go | 1 - core/services/ocr2/plugins/s4/plugin_test.go | 1 - core/services/ocrcommon/adapters_test.go | 1 - core/services/ocrcommon/block_translator_test.go | 1 - core/services/ocrcommon/data_source.go | 1 - core/services/ocrcommon/data_source_test.go | 1 - core/services/ocrcommon/discoverer_database_test.go | 1 - core/services/ocrcommon/peer_wrapper_test.go | 1 - core/services/ocrcommon/telemetry_test.go | 4 ---- core/services/ocrcommon/transmitter.go | 2 -- core/services/periodicbackup/backup_test.go | 1 - core/services/pg/connection_test.go | 1 - core/services/pg/stats.go | 1 - core/services/pg/stats_test.go | 1 - core/services/pipeline/common_eth.go | 1 - core/services/pipeline/common_http.go | 1 - core/services/pipeline/common_test.go | 1 - core/services/pipeline/graph_test.go | 1 - core/services/pipeline/orm.go | 1 - core/services/pipeline/orm_test.go | 2 -- core/services/pipeline/runner.go | 1 - core/services/pipeline/runner_test.go | 2 -- core/services/pipeline/scheduler.go | 1 - core/services/pipeline/scheduler_test.go | 1 - core/services/pipeline/task.bridge_test.go | 5 ----- core/services/pipeline/task.eth_tx_test.go | 2 -- core/services/pipeline/task.http_test.go | 1 - core/services/pipeline/task_object_params.go | 1 - core/services/pipeline/task_params.go | 1 - core/services/pipeline/task_params_test.go | 1 - core/services/relay/evm/config_poller_test.go | 1 - core/services/relay/evm/evm.go | 4 ---- .../services/relay/evm/functions/contract_transmitter.go | 1 - core/services/relay/evm/mercury/orm_test.go | 1 - core/services/relay/evm/mercury/wsrpc/pool.go | 1 - core/services/relay/evm/ocr2keeper.go | 1 - core/services/relay/evm/ocr2vrf.go | 2 -- core/services/relay/evm/relayer_extender.go | 1 - core/services/relay/evm/relayer_extender_test.go | 1 - core/services/relay/evm/types/size_helper_test.go | 2 -- core/services/signatures/ethdss/ethdss_test.go | 1 - core/services/signatures/secp256k1/field_test.go | 1 - .../services/synchronization/telemetry_ingress_client.go | 1 - .../synchronization/telemetry_ingress_client_test.go | 1 - core/services/telemetry/manager.go | 2 -- core/services/telemetry/manager_test.go | 4 ---- core/services/vrf/v2/coordinator_v2x_interface.go | 1 - core/services/vrf/v2/reverted_txns.go | 4 ---- core/services/workflows/engine_test.go | 1 - core/services/workflows/models_yaml_test.go | 1 - core/store/migrate/migrate_test.go | 3 --- core/store/models/errors.go | 1 - core/utils/collection_test.go | 2 -- core/utils/deferable_write_closer.go | 2 -- core/utils/deferable_write_closer_test.go | 1 - core/utils/utils.go | 1 - core/utils/utils_test.go | 1 - core/web/common.go | 1 - core/web/cors_test.go | 1 - core/web/cosmos_chains_controller_test.go | 1 - core/web/dkgencrypt_keys_controller_test.go | 1 - core/web/dkgsign_keys_controller_test.go | 1 - core/web/eth_keys_controller.go | 2 -- core/web/eth_keys_controller_test.go | 2 -- core/web/evm_chains_controller_test.go | 1 - core/web/evm_forwarders_controller_test.go | 1 - core/web/jobs_controller_test.go | 1 - core/web/lca_controller.go | 1 - core/web/log_controller_test.go | 2 -- core/web/loop_registry.go | 1 - core/web/resolver/chain_test.go | 3 --- core/web/resolver/helpers.go | 1 - core/web/resolver/job_proposal_spec_test.go | 2 -- core/web/resolver/node_test.go | 1 - core/web/router.go | 1 - tools/flakeytests/runner.go | 2 -- 207 files changed, 1 insertion(+), 332 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 7f127e9524d..2902503ed20 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -14,6 +14,7 @@ linters: - sqlclosecheck - noctx - depguard + - whitespace linters-settings: exhaustive: default-signifies-exhaustive: true diff --git a/common/client/multi_node.go b/common/client/multi_node.go index fa413df91aa..af8ff03f534 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -239,7 +239,6 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return rpc, err } return n.RPC(), nil - } // selectNode returns the active Node, if it is still nodeStateAlive, otherwise it selects a new one from the NodeSelector. @@ -641,7 +640,6 @@ loop: // ignore critical error as it's reported in reportSendTxAnomalies result, _ := aggregateTxResults(errorsByCode) return result - } func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { @@ -759,7 +757,6 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP c.wg.Add(1) go c.reportSendTxAnomalies(tx, txResultsToReport) - }) if !ok { return fmt.Errorf("aborted while broadcasting tx - multiNode is stopped: %w", context.Canceled) diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 9f6904fcaf2..d602fa30afd 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -373,7 +373,6 @@ func TestMultiNode_selectNode(t *testing.T) { newActiveNode, err := mn.selectNode() require.NoError(t, err) require.Equal(t, prevActiveNode.String(), newActiveNode.String()) - }) t.Run("Updates node if active is not healthy", func(t *testing.T) { t.Parallel() @@ -399,7 +398,6 @@ func TestMultiNode_selectNode(t *testing.T) { newActiveNode, err := mn.selectNode() require.NoError(t, err) require.Equal(t, newBest.String(), newActiveNode.String()) - }) t.Run("No active nodes - reports critical error", func(t *testing.T) { t.Parallel() @@ -418,7 +416,6 @@ func TestMultiNode_selectNode(t *testing.T) { require.EqualError(t, err, ErroringNodeError.Error()) require.Nil(t, node) tests.RequireLogMessage(t, observedLogs, "No live RPC nodes available") - }) } diff --git a/common/client/node_fsm_test.go b/common/client/node_fsm_test.go index 36cee65e09e..dc0ca0e7de8 100644 --- a/common/client/node_fsm_test.go +++ b/common/client/node_fsm_test.go @@ -118,7 +118,6 @@ func testTransition(t *testing.T, rpc *mockNodeClient[types.ID, Head], transitio }, "Expected transition from `%s` to `%s` to panic", nodeState, destinationState) m.AssertNotCalled(t) assert.Equal(t, nodeState, node.State(), "Expected node to remain in initial state on invalid transition") - } } diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 4707a60426f..fa6397580c8 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -259,7 +259,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { n.stateLatestFinalizedBlockNumber = latestFinalizedBN } } - } } @@ -524,6 +523,5 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { n.declareAlive() return } - } } diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index b3c09b35000..4bdfd698f7a 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -39,7 +39,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { node.setState(nodeStateClosed) node.wg.Add(1) node.aliveLoop() - }) t.Run("if initial subscribe fails, transitions to unreachable", func(t *testing.T) { t.Parallel() @@ -58,7 +57,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { tests.AssertEventually(t, func() bool { return node.State() == nodeStateUnreachable }) - }) t.Run("if remote RPC connection is closed transitions to unreachable", func(t *testing.T) { t.Parallel() @@ -150,7 +148,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { tests.AssertLogCountEventually(t, observedLogs, fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", node.String()), pollFailureThreshold) tests.AssertLogCountEventually(t, observedLogs, "Version poll successful", 2) assert.True(t, ensuredAlive.Load(), "expected to ensure that node was alive") - }) t.Run("with threshold poll failures, transitions to unreachable", func(t *testing.T) { t.Parallel() @@ -356,7 +353,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { node.declareAlive() tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed") assert.Equal(t, nodeStateUnreachable, node.State()) - }) t.Run("updates block number and difficulty on new head", func(t *testing.T) { t.Parallel() @@ -859,7 +855,6 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { node.setState(nodeStateClosed) node.wg.Add(1) node.unreachableLoop() - }) t.Run("on failed redial, keeps trying", func(t *testing.T) { t.Parallel() @@ -1017,7 +1012,6 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { node.setState(nodeStateClosed) node.wg.Add(1) node.invalidChainIDLoop() - }) t.Run("on invalid dial becomes unreachable", func(t *testing.T) { t.Parallel() @@ -1380,7 +1374,6 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { } } } - }) t.Run("total difficulty selection mode", func(t *testing.T) { const syncThreshold = 10 @@ -1432,7 +1425,6 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { }) } } - }) } @@ -1453,7 +1445,6 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { node.setState(nodeStateClosed) node.wg.Add(1) node.syncingLoop() - }) t.Run("on invalid dial becomes unreachable", func(t *testing.T) { t.Parallel() diff --git a/common/internal/utils/utils.go b/common/internal/utils/utils.go index 1e285868c53..aeaad34a142 100644 --- a/common/internal/utils/utils.go +++ b/common/internal/utils/utils.go @@ -17,7 +17,6 @@ func NewRedialBackoff() backoff.Backoff { Max: 15 * time.Second, Jitter: true, } - } // MinFunc returns the minimum value of the given element array with respect diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index 1651f6417bf..2a9c1231d7b 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -598,7 +598,6 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand // trying to send the transaction over again. return fmt.Errorf("retryable error while sending transaction %s (tx ID %d): %w", attempt.Hash.String(), etx.ID, err), true } - } // Finds next transaction in the queue, assigns a sequence, and moves it to "in_progress" state ready for broadcast. diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index d61f9a3dddd..dd98df0a8fe 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -814,7 +814,6 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bum func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleInProgressAttempt(ctx context.Context, lggr logger.SugaredLogger, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockHeight int64) error { if attempt.State != txmgrtypes.TxAttemptInProgress { - return fmt.Errorf("invariant violation: expected tx_attempt %v to be in_progress, it was %s", attempt.ID, attempt.State) } @@ -1049,7 +1048,6 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For ec.lggr.Infof("ForceRebroadcast: will rebroadcast transactions for all sequences between %v and %v", seqs[0], seqs[len(seqs)-1]) for _, seq := range seqs { - etx, err := ec.txStore.FindTxWithSequence(ctx, address, seq) if err != nil { return fmt.Errorf("ForceRebroadcast failed: %w", err) @@ -1098,7 +1096,6 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) sen // ResumePendingTaskRuns issues callbacks to task runs that are pending waiting for receipts func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ResumePendingTaskRuns(ctx context.Context, head types.Head[BLOCK_HASH]) error { - receiptsPlus, err := ec.txStore.FindTxesPendingCallback(ctx, head.BlockNumber(), ec.chainID) if err != nil { diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 4865116196e..3c7bdf2c971 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -147,7 +147,6 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error r.m[id] = c r.lggr.Infow("capability added", "id", id, "type", info.CapabilityType, "description", info.Description, "version", info.Version) return nil - } // NewRegistry returns a new Registry. diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index 744fcd9d2e7..96da502f10d 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -79,7 +79,6 @@ func TestEvmWrite(t *testing.T) { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, // len = 3 0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // elements [1, 2, 3] zero padded }, payload["data"]) - }) ch, err := capability.Execute(ctx, req) diff --git a/core/chains/evm/assets/wei.go b/core/chains/evm/assets/wei.go index 3621e4492a4..4fcdc15146b 100644 --- a/core/chains/evm/assets/wei.go +++ b/core/chains/evm/assets/wei.go @@ -117,7 +117,6 @@ func (w *Wei) text(suf string, exp int32) string { return "0" } return fmt.Sprintf("%s %s", d, suf) - } const u64Eth = 1_000_000_000_000_000_000 @@ -201,7 +200,6 @@ func (w *Wei) UnmarshalText(b []byte) error { } *w = (Wei)(*d.BigInt()) return nil - } // unrecognized or missing suffix d, err := decimal.NewFromString(s) diff --git a/core/chains/evm/client/client_test.go b/core/chains/evm/client/client_test.go index 62acf146e48..99053bd5aec 100644 --- a/core/chains/evm/client/client_test.go +++ b/core/chains/evm/client/client_test.go @@ -308,7 +308,6 @@ func TestEthClient_GetERC20Balance(t *testing.T) { assert.Equal(t, strings.ToLower(contractAddress.Hex()), callArgs.Get("to").String()) && assert.Equal(t, hexutil.Encode(txData), callArgs.Get("data").String()) && assert.Equal(t, "latest", arr[1].String()) { - resp.Result = `"` + hexutil.EncodeBig(test.balance) + `"` } return @@ -907,7 +906,6 @@ func TestEthClient_ErroringClient(t *testing.T) { _, err = erroringClient.TransactionReceipt(ctx, common.Hash{}) require.Equal(t, err, commonclient.ErroringNodeError) - } const headResult = client.HeadResult diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index 744abb89f60..bdf7bfbe726 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -94,7 +94,6 @@ func Test_Eth_Errors(t *testing.T) { }) t.Run("IsReplacementUnderpriced", func(t *testing.T) { - tests := []errorCase{ {"replacement transaction underpriced", true, "geth"}, {"Replacement transaction underpriced", true, "Besu"}, diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index 1db8958443c..7e2771a67d5 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -196,7 +196,6 @@ func NewChainClientWithEmptyNode( noNewHeadsThreshold time.Duration, chainID *big.Int, ) Client { - lggr := logger.Test(t) var chainType commonconfig.ChainType @@ -213,7 +212,6 @@ func NewChainClientWithMockedRpc( chainID *big.Int, rpc RPCClient, ) Client { - lggr := logger.Test(t) var chainType commonconfig.ChainType diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go index 474ff2700b4..92b7a8301e5 100644 --- a/core/chains/evm/client/node.go +++ b/core/chains/evm/client/node.go @@ -828,7 +828,6 @@ func (n *node) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumb ) return - } func (n *node) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) (val []byte, err error) { @@ -855,7 +854,6 @@ func (n *node) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) (v ) return - } func (n *node) BlockByNumber(ctx context.Context, number *big.Int) (b *types.Block, err error) { diff --git a/core/chains/evm/client/node_lifecycle_test.go b/core/chains/evm/client/node_lifecycle_test.go index 0fcaf54ae3d..878ecabe600 100644 --- a/core/chains/evm/client/node_lifecycle_test.go +++ b/core/chains/evm/client/node_lifecycle_test.go @@ -502,7 +502,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { state, num, _ := n.StateAndLatest() assert.Equal(t, NodeStateAlive, state) assert.Equal(t, int64(stall), num) - }) } diff --git a/core/chains/evm/client/pool_test.go b/core/chains/evm/client/pool_test.go index 462aeed43ee..5f614b7ed24 100644 --- a/core/chains/evm/client/pool_test.go +++ b/core/chains/evm/client/pool_test.go @@ -392,5 +392,4 @@ func TestUnit_Pool_LeaseDuration(t *testing.T) { nodeSwitch.isAlive = true nodeSwitch.mu.Unlock() testutils.WaitForLogMessage(t, observedLogs, `Switching to best node from "n2" to "n1"`) - } diff --git a/core/chains/evm/client/sub_error_wrapper_test.go b/core/chains/evm/client/sub_error_wrapper_test.go index 457d392a50e..5dd81069572 100644 --- a/core/chains/evm/client/sub_error_wrapper_test.go +++ b/core/chains/evm/client/sub_error_wrapper_test.go @@ -70,6 +70,5 @@ func TestSubscriptionErrorWrapper(t *testing.T) { _, ok = <-wrapper.Err() return !ok }) - }) } diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index 7a7a274127f..3f09d9b7679 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -189,7 +189,6 @@ func (f *FwdMgr) initForwardersCache(ctx context.Context, fwdrs []Forwarder) { continue } f.setCachedSenders(fwdr.Address, senders) - } } diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index 43f42c69203..1eeedf43896 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -1599,7 +1599,6 @@ func TestBlockHistoryEstimator_EffectiveGasPrice(t *testing.T) { res := bhe.EffectiveGasPrice(eipblock, tx) assert.Nil(t, res) }) - } func TestBlockHistoryEstimator_Block_Unmarshal(t *testing.T) { @@ -2343,7 +2342,6 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 10 wei, which is above percentile=60%% (percentile tip cap: 6 wei) for blocks 3 thru 3 (checking 1 blocks)", attempts[0].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) }) - }) t.Run("in EIP-1559 mode", func(t *testing.T) { diff --git a/core/chains/evm/gas/fixed_price_estimator.go b/core/chains/evm/gas/fixed_price_estimator.go index f4749b093a1..7ac086bf067 100644 --- a/core/chains/evm/gas/fixed_price_estimator.go +++ b/core/chains/evm/gas/fixed_price_estimator.go @@ -118,7 +118,6 @@ func (f *fixedPriceEstimator) BumpDynamicFee( maxGasPriceWei *assets.Wei, _ []EvmPriorAttempt, ) (bumped DynamicFee, err error) { - return BumpDynamicFeeOnly( f.config, f.bhConfig.EIP1559FeeCapBufferBlocks(), diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go index e53ea0cd629..78058efa560 100644 --- a/core/chains/evm/headtracker/head_saver_test.go +++ b/core/chains/evm/headtracker/head_saver_test.go @@ -143,5 +143,4 @@ func TestHeadSaver_Load(t *testing.T) { uncleChain := saver.Chain(h2Uncle.Hash) require.NotNil(t, uncleChain) require.Equal(t, uint32(2), uncleChain.ChainLength()) // h2Uncle -> h1 - } diff --git a/core/chains/evm/headtracker/heads_test.go b/core/chains/evm/headtracker/heads_test.go index 4241b462363..2f468e0f541 100644 --- a/core/chains/evm/headtracker/heads_test.go +++ b/core/chains/evm/headtracker/heads_test.go @@ -154,10 +154,8 @@ func TestHeads_MarkFinalized(t *testing.T) { require.True(t, heads.HeadByHash(head.Hash).IsFinalized, "expected h3 and all ancestors to be finalized", head.BlockNumber()) } require.False(t, heads.HeadByHash(h2Uncle.Hash).IsFinalized, "expected uncle block not to be marked as finalized") - } t.Run("blocks were correctly marked as finalized", ensureProperFinalization) heads.AddHeads(h0, h1, h2, h2Uncle, h3, h4, h5) t.Run("blocks remain finalized after re adding them to the Heads", ensureProperFinalization) - } diff --git a/core/chains/evm/log/eth_subscriber.go b/core/chains/evm/log/eth_subscriber.go index e5ba202dbf2..3d251a331a3 100644 --- a/core/chains/evm/log/eth_subscriber.go +++ b/core/chains/evm/log/eth_subscriber.go @@ -104,7 +104,6 @@ func (sub *ethSubscriber) backfillLogs(fromBlockOverride sql.NullInt64, addresse // On ethereum its 15MB [https://github.com/ethereum/go-ethereum/blob/master/rpc/websocket.go#L40] batchSize := int64(sub.config.LogBackfillBatchSize()) for from := q.FromBlock.Int64(); from <= latestHeight; from += batchSize { - to := from + batchSize - 1 if to > latestHeight { to = latestHeight @@ -204,7 +203,6 @@ func (sub *ethSubscriber) createSubscription(addresses []common.Address, topics defer cancel() utils.RetryWithBackoff(ctx, func() (retry bool) { - filterQuery := ethereum.FilterQuery{ Addresses: addresses, Topics: [][]common.Hash{topics}, diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index 13aeb8d2338..7f216e8545e 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -146,7 +146,6 @@ func (helper *broadcasterHelper) registerWithTopics(listener log.Listener, contr func (helper *broadcasterHelper) registerWithTopicValues(listener log.Listener, contract log.AbigenContract, numConfirmations uint32, topics map[common.Hash][][]log.Topic) { - unsubscribe := helper.lb.Register(listener, log.ListenerOpts{ Contract: contract.Address(), ParseLog: contract.ParseLog, @@ -328,10 +327,8 @@ func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb lo return false } if !consumed && !listener.skipMarkingConsumed.Load() { - err = listener.MarkConsumed(ctx, lb) if assert.NoError(t, err) { - consumed2, err := listener.WasAlreadyConsumed(ctx, lb) if assert.NoError(t, err) { assert.True(t, consumed2) diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index e34533b3cfb..6c06be93dbe 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -241,7 +241,6 @@ func TestBroadcaster_ReplaysLogs(t *testing.T) { <-cltest.SimulateIncomingHeads(t, blocks.Slice(12, 13), helper.lb) require.Eventually(t, func() bool { return len(listener.getUniqueLogs()) == 4 }, testutils.WaitTimeout(t), time.Second, "expected unique logs to be 4 but was %d", len(listener.getUniqueLogs())) - }() require.Eventually(t, func() bool { return helper.mockEth.UnsubscribeCallCount() >= 1 }, testutils.WaitTimeout(t), time.Second) diff --git a/core/chains/evm/log/registrations.go b/core/chains/evm/log/registrations.go index c82fee43b6e..68dd93b9d88 100644 --- a/core/chains/evm/log/registrations.go +++ b/core/chains/evm/log/registrations.go @@ -225,7 +225,6 @@ func (r *registrations) sendLogs(ctx context.Context, logsToSend []logsOnBlock, for _, logsPerBlock := range logsToSend { for numConfirmations, handlers := range r.handlersByConfs { - if numConfirmations != 0 && latestBlockNumber < uint64(numConfirmations) { // Skipping send because the block is definitely too young continue @@ -392,7 +391,6 @@ func (r *handler) sendLog(ctx context.Context, log types.Log, latestHead evmtype broadcasts map[LogBroadcastAsKey]bool, bc broadcastCreator, logger logger.Logger) { - topic := log.Topics[0] latestBlockNumber := uint64(latestHead.Number) diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index 4236f0b8ef1..b7dbb074568 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -268,7 +268,6 @@ func mockBatchCallContext(t *testing.T, ec *evmclimocks.Client) { } result := e.Result.(*evmtypes.Head) *result = evmtypes.Head{Number: num, Hash: utils.NewHash()} - } }) } diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index cb211043a4c..097c6f9eef2 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -75,7 +75,6 @@ func populateDatabase(t testing.TB, o logpoller.ORM, chainID *big.Int) (common.H Data: logpoller.EvmWord(uint64(i + 1000*j)).Bytes(), CreatedAt: blockTimestamp, }) - } require.NoError(t, o.InsertLogs(ctx, logs)) require.NoError(t, o.InsertBlock(ctx, utils.RandomHash(), int64((j+1)*1000-1), startDate.Add(time.Duration(j*1000)*time.Hour), 0)) @@ -1956,7 +1955,6 @@ func TestFindLCA(t *testing.T) { }).Once() _, err := lp.FindLCA(lCtx) require.ErrorContains(t, err, "aborted, FindLCA request cancelled") - }) t.Run("Fails, if RPC returns an error", func(t *testing.T) { expectedError := fmt.Errorf("failed to call RPC") diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index d065553886e..5084e0329a7 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -154,7 +154,6 @@ func (o *DSORM) DeleteFilter(ctx context.Context, name string) error { `DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, ubig.New(o.chainID)) return err - } // LoadFilters returns all filters for this chain diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 2a1be62dd5b..c89a39aa6b4 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -1728,7 +1728,6 @@ func Benchmark_DeleteExpiredLogs(b *testing.B) { for j := 0; j < 5; j++ { var dbLogs []logpoller.Log for i := 0; i < numberOfReports; i++ { - dbLogs = append(dbLogs, logpoller.Log{ EvmChainId: ubig.New(chainId), LogIndex: int64(i + 1), diff --git a/core/chains/evm/monitor/balance.go b/core/chains/evm/monitor/balance.go index 28bcdd9abdf..5ef41b63be1 100644 --- a/core/chains/evm/monitor/balance.go +++ b/core/chains/evm/monitor/balance.go @@ -103,7 +103,6 @@ func (bm *balanceMonitor) OnNewLongestChain(_ context.Context, head *evmtypes.He if !ok { bm.logger.Debugw("BalanceMonitor: ignoring OnNewLongestChain call, balance monitor is not started", "state", bm.State()) } - } func (bm *balanceMonitor) checkBalance(head *evmtypes.Head) { diff --git a/core/chains/evm/testutils/config_test.go b/core/chains/evm/testutils/config_test.go index 0cbcc5eb63b..1f9d7be4445 100644 --- a/core/chains/evm/testutils/config_test.go +++ b/core/chains/evm/testutils/config_test.go @@ -18,5 +18,4 @@ func TestNewTestChainScopedConfigOverride(t *testing.T) { assert.Equal(t, uint32(100), c.EVM().FinalityDepth()) // fallback.toml values assert.Equal(t, false, c.EVM().GasEstimator().EIP1559DynamicFees()) - } diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index aa1fa8cdeb2..bf2d9a68edf 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -138,7 +138,6 @@ func (c *evmTxAttemptBuilder) NewEmptyTxAttempt(ctx context.Context, nonce evmty attempt.SignedRawTx = signedTxBytes attempt.Hash = hash return attempt, nil - } func (c *evmTxAttemptBuilder) newDynamicFeeAttempt(ctx context.Context, etx Tx, fee gas.DynamicFee, gasLimit uint64) (attempt TxAttempt, err error) { diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 20c069a46d6..c80ae781034 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -1094,7 +1094,6 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // Saved NextNonce must be the same as before because this transaction // was not accepted by the eth node and never can be require.Equal(t, int64(localNextNonce), int64(nonce)) - }) t.Run("with callback", func(t *testing.T) { @@ -1641,7 +1640,6 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // TEARDOWN: Clear out the unsent tx before the next test pgtest.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce) }) - } func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 44449b7a44f..db2d8a9092f 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -315,7 +315,6 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_1.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[1], attempt2_1.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // First transaction confirmed @@ -376,7 +375,6 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { cltest.BatchElemMatchesParams(b[2], attempt2_1.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[1], attempt2_2.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[0], attempt2_3.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // Most expensive attempt still unconfirmed @@ -933,7 +931,6 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { cltest.BatchElemMatchesParams(b[3], attempt1_1.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[4], attempt2_1.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[5], attempt3_1.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // First transaction confirmed @@ -999,7 +996,6 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[2], attempt2_1.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // First transaction still unconfirmed @@ -1046,7 +1042,6 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // Both attempts still unconfirmed @@ -1087,7 +1082,6 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // Both attempts still unconfirmed diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index dedba07b594..22b9b6678fa 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1236,7 +1236,6 @@ func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, tim } if _, err := orm.q.ExecContext(ctx, `UPDATE evm.txes SET state = 'confirmed_missing_receipt' WHERE id = $1`, attempt.TxID); err != nil { return pkgerrors.Wrap(err, "failed to update evm.txes") - } return nil }) @@ -1778,7 +1777,6 @@ func (o *evmTxStore) CreateTransaction(ctx context.Context, txRequest TxRequest, var dbEtx DbEthTx err = o.Transact(ctx, false, func(orm *evmTxStore) error { if txRequest.PipelineTaskRunID != nil { - err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, txRequest.PipelineTaskRunID, chainID.String()) // If no eth_tx matches (the common case) then continue if !errors.Is(err, sql.ErrNoRows) { diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index cf38b2d1275..20b39f3a83e 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -1027,7 +1027,6 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { attemptResult, err := txStore.FindTxAttempt(ctx, attempt.Hash) require.NoError(t, err) assert.Equal(t, txmgrtypes.TxAttemptInProgress, attemptResult.State) - }) } diff --git a/core/chains/evm/txmgr/nonce_tracker.go b/core/chains/evm/txmgr/nonce_tracker.go index 6fb708ed876..941775b7e85 100644 --- a/core/chains/evm/txmgr/nonce_tracker.go +++ b/core/chains/evm/txmgr/nonce_tracker.go @@ -77,7 +77,6 @@ func (s *nonceTracker) getSequenceForAddr(ctx context.Context, address common.Ad } s.lggr.Criticalw("failed to retrieve next sequence from on-chain for address: ", "address", address.String()) return seq, err - } // syncSequence tries to sync the key sequence, retrying indefinitely until success or stop signal is sent diff --git a/core/chains/evm/txmgr/nonce_tracker_test.go b/core/chains/evm/txmgr/nonce_tracker_test.go index c6af58ab7ac..17c042e375e 100644 --- a/core/chains/evm/txmgr/nonce_tracker_test.go +++ b/core/chains/evm/txmgr/nonce_tracker_test.go @@ -72,7 +72,6 @@ func TestNonceTracker_LoadSequenceMap(t *testing.T) { require.NoError(t, err) require.Equal(t, types.Nonce(randNonce2), seq) }) - } func TestNonceTracker_syncOnChain(t *testing.T) { @@ -129,7 +128,6 @@ func TestNonceTracker_syncOnChain(t *testing.T) { require.NoError(t, err) require.Equal(t, types.Nonce(nonce), seq) }) - } func TestNonceTracker_SyncSequence(t *testing.T) { @@ -196,7 +194,6 @@ func TestNonceTracker_GetNextSequence(t *testing.T) { t.Run("fails to get sequence if address doesn't exist in map", func(t *testing.T) { _, err := nonceTracker.GetNextSequence(ctx, addr) require.Error(t, err) - }) t.Run("fails to get sequence if address doesn't exist in map and is disabled", func(t *testing.T) { @@ -227,7 +224,6 @@ func TestNonceTracker_GetNextSequence(t *testing.T) { seq, err := nonceTracker.GetNextSequence(ctx, addr) require.NoError(t, err) require.Equal(t, types.Nonce(txStoreNonce+1), seq) - }) } diff --git a/core/chains/evm/txmgr/transmitchecker.go b/core/chains/evm/txmgr/transmitchecker.go index 8956f2ae626..8d36903ac6a 100644 --- a/core/chains/evm/txmgr/transmitchecker.go +++ b/core/chains/evm/txmgr/transmitchecker.go @@ -357,5 +357,4 @@ func (v *VRFV2Checker) Check( "meta", tx.Meta, "vrfRequestId", vrfRequestID) return nil - } diff --git a/core/chains/evm/types/address.go b/core/chains/evm/types/address.go index 4a77ce5f8db..3c8b0621a9d 100644 --- a/core/chains/evm/types/address.go +++ b/core/chains/evm/types/address.go @@ -92,7 +92,6 @@ func (a *EIP55Address) UnmarshalJSON(input []byte) error { // Value returns this instance serialized for database storage. func (a EIP55Address) Value() (driver.Value, error) { return a.Bytes(), nil - } // Scan reads the database value and returns an instance. diff --git a/core/chains/evm/types/block_json_benchmark_test.go b/core/chains/evm/types/block_json_benchmark_test.go index 21c58bd1987..766b9099819 100644 --- a/core/chains/evm/types/block_json_benchmark_test.go +++ b/core/chains/evm/types/block_json_benchmark_test.go @@ -73,7 +73,6 @@ func unmarshal_block(b *testing.B, block *evmtypes.Block) { func BenchmarkBlock_Small_JSONUnmarshal(b *testing.B) { unmarshal_block(b, smallBlock) - } func BenchmarkBlock_Medium_JSONUnmarshal(b *testing.B) { diff --git a/core/chains/evm/types/head_test.go b/core/chains/evm/types/head_test.go index b4f1de25c6e..97c536a3444 100644 --- a/core/chains/evm/types/head_test.go +++ b/core/chains/evm/types/head_test.go @@ -47,5 +47,4 @@ func TestHead_LatestFinalizedHead(t *testing.T) { } }) } - } diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 1bf47f84726..7e9d41205bf 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -369,7 +369,6 @@ var ErrMissingBlock = pkgerrors.New("missing block") // UnmarshalJSON unmarshals to a Block func (b *Block) UnmarshalJSON(data []byte) error { - var h codec.Handle = new(codec.JsonHandle) bi := blocks.BlockInternal{} @@ -419,7 +418,6 @@ const LegacyTxType = blocks.TxType(0x0) // UnmarshalJSON unmarshals a Transaction func (t *Transaction) UnmarshalJSON(data []byte) error { - var h codec.Handle = new(codec.JsonHandle) ti := blocks.TransactionInternal{} @@ -443,7 +441,6 @@ func (t *Transaction) UnmarshalJSON(data []byte) error { } func (t *Transaction) MarshalJSON() ([]byte, error) { - ti := toInternalTxn(*t) buf := bytes.NewBuffer(make([]byte, 0, 256)) diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index ef355a01bda..4757ddab5e6 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -1096,7 +1096,6 @@ func TestTransaction_UnmarshalJSON(t *testing.T) { err := got.UnmarshalJSON(tt.args.data) require.NoError(t, err) require.Equal(t, tt.want, got) - }) } } @@ -1149,7 +1148,6 @@ func assertTxnsEqual(t *testing.T, txns1, txns2 []evmtypes.Transaction) { } } func TestTxType_JSONRoundtrip(t *testing.T) { - t.Run("non zero", func(t *testing.T) { t.Parallel() want := evmtypes.TxType(2) diff --git a/core/chains/evm/utils/ethabi_test.go b/core/chains/evm/utils/ethabi_test.go index f28a083ff01..71cf15194d7 100644 --- a/core/chains/evm/utils/ethabi_test.go +++ b/core/chains/evm/utils/ethabi_test.go @@ -275,7 +275,6 @@ func TestEVMTranscodeBool(t *testing.T) { for _, tt := range tests { test := tt t.Run(test.name, func(t *testing.T) { - out, err := EVMTranscodeBool(test.input) assert.NoError(t, err) assert.Equal(t, test.output, hexutil.Encode(out)) @@ -361,7 +360,6 @@ func TestEVMTranscodeUint256(t *testing.T) { for _, tt := range tests { test := tt t.Run(test.name, func(t *testing.T) { - out, err := EVMTranscodeUint256(test.input) if test.wantError { assert.Error(t, err) @@ -451,7 +449,6 @@ func TestEVMTranscodeInt256(t *testing.T) { for _, tt := range tests { test := tt t.Run(test.name, func(t *testing.T) { - out, err := EVMTranscodeInt256(test.input) if test.wantError { assert.Error(t, err) diff --git a/core/chains/evm/utils/utils.go b/core/chains/evm/utils/utils.go index 85ae358e597..708a0ac5ff8 100644 --- a/core/chains/evm/utils/utils.go +++ b/core/chains/evm/utils/utils.go @@ -186,7 +186,6 @@ func NewRedialBackoff() backoff.Backoff { Max: 15 * time.Second, Jitter: true, } - } // RetryWithBackoff retries the sleeper and backs off if not Done diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go index c10712d4b6b..a9297aa3b68 100644 --- a/core/chains/legacyevm/chain_test.go +++ b/core/chains/legacyevm/chain_test.go @@ -28,7 +28,6 @@ func TestLegacyChains(t *testing.T) { got, err := l.Get(c.ID().String()) assert.NoError(t, err) assert.Equal(t, c, got) - } func TestChainOpts_Validate(t *testing.T) { diff --git a/core/cmd/app.go b/core/cmd/app.go index 27757ae4d24..378f7e8bd64 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -128,7 +128,6 @@ func NewApp(s *Shell) *cli.App { } return nil - } app.After = func(c *cli.Context) error { if s.CloseLogger != nil { diff --git a/core/cmd/cosmos_keys_commands_test.go b/core/cmd/cosmos_keys_commands_test.go index 7c3b4ed19f7..a0a211a1984 100644 --- a/core/cmd/cosmos_keys_commands_test.go +++ b/core/cmd/cosmos_keys_commands_test.go @@ -80,7 +80,6 @@ func TestShell_CosmosKeys(t *testing.T) { require.Equal(t, 1, len(r.Renders)) keys := *r.Renders[0].(*cmd.CosmosKeyPresenters) assert.True(t, key.PublicKeyStr() == keys[0].PubKey) - }) t.Run("CreateCosmosKey", func(tt *testing.T) { diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index 5375abbacee..da153f6884b 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -190,7 +190,6 @@ func TestShell_SendEther_From_Txm(t *testing.T) { require.NoError(t, err) require.Len(t, attempts, 1) assert.Equal(t, attempts[0].Hash, output.Hash) - } func TestShell_SendEther_From_Txm_WEI(t *testing.T) { diff --git a/core/cmd/ocr2_keys_commands_test.go b/core/cmd/ocr2_keys_commands_test.go index b0c62f01aa5..c2fab273498 100644 --- a/core/cmd/ocr2_keys_commands_test.go +++ b/core/cmd/ocr2_keys_commands_test.go @@ -135,7 +135,6 @@ func TestShell_OCR2Keys(t *testing.T) { require.Equal(t, 1, len(r.Renders)) output := *r.Renders[0].(*cmd.OCR2KeyBundlePresenter) assert.Equal(t, key.ID(), output.ID) - }) t.Run("ImportExportOCR2Key", func(tt *testing.T) { diff --git a/core/cmd/shell.go b/core/cmd/shell.go index adbb66ce63f..a12f80f168b 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -203,7 +203,6 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G TOMLConfigs: cfg.StarknetConfigs(), } initOps = append(initOps, chainlink.InitStarknet(ctx, relayerFactory, starkCfg)) - } relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index e7322e513ae..5fbbff4260f 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -56,7 +56,6 @@ func genTestEVMRelayers(t *testing.T, opts legacyevm.ChainRelayExtenderConfig, k t.Fatal(err) } return relayers - } func TestShell_RunNodeWithPasswords(t *testing.T) { @@ -491,7 +490,6 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { app.On("GetConfig").Return(config).Once() require.NoError(t, client.RebroadcastTransactions(c)) } - }) } } diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index cdbe12d66b4..f4661a58e82 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -258,7 +258,6 @@ func TestShell_DestroyExternalInitiator_NotFound(t *testing.T) { } func TestShell_RemoteLogin(t *testing.T) { - app := startNewApplicationV2(t, nil) orm := app.AuthenticationProvider() @@ -492,7 +491,6 @@ func TestShell_Profile_InvalidSecondsParam(t *testing.T) { err = client.Profile(cli.NewContext(nil, set, nil)) wantErr := cmd.ErrProfileTooLong require.ErrorAs(t, err, &wantErr) - } func TestShell_Profile(t *testing.T) { diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index d9ac44b46ef..1e3b93851f3 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -335,7 +335,6 @@ func TestFileSessionRequestBuilder(t *testing.T) { } func TestNewUserCache(t *testing.T) { - r, err := rand.Int(rand.Reader, big.NewInt(256*1024*1024)) require.NoError(t, err) // NewUserCache owns it's Dir. @@ -350,7 +349,6 @@ func TestNewUserCache(t *testing.T) { }() assert.DirExists(t, c.RootDir()) - } func TestSetupSolanaRelayer(t *testing.T) { @@ -603,11 +601,9 @@ func flagSetApplyFromAction(action interface{}, flagSet *flag.FlagSet, parentCom flag.Apply(flagSet) } } - } func recursiveFindFlagsWithName(actionFuncName string, command cli.Command, parent string, foundName bool) []cli.Flag { - if command.Action != nil { if actionFuncName == getFuncName(command.Action) && foundName { return command.Flags diff --git a/core/cmd/solana_keys_commands_test.go b/core/cmd/solana_keys_commands_test.go index 897031877c1..02b06f6596a 100644 --- a/core/cmd/solana_keys_commands_test.go +++ b/core/cmd/solana_keys_commands_test.go @@ -80,7 +80,6 @@ func TestShell_SolanaKeys(t *testing.T) { require.Equal(t, 1, len(r.Renders)) keys := *r.Renders[0].(*cmd.SolanaKeyPresenters) assert.True(t, key.PublicKeyStr() == keys[0].PubKey) - }) t.Run("CreateSolanaKey", func(tt *testing.T) { diff --git a/core/cmd/starknet_keys_commands_test.go b/core/cmd/starknet_keys_commands_test.go index 5823a80b46d..4f4b0bf6b77 100644 --- a/core/cmd/starknet_keys_commands_test.go +++ b/core/cmd/starknet_keys_commands_test.go @@ -79,7 +79,6 @@ func TestShell_StarkNetKeys(t *testing.T) { require.Equal(t, 1, len(r.Renders)) keys := *r.Renders[0].(*cmd.StarkNetKeyPresenters) assert.True(t, key.StarkKeyStr() == keys[0].StarkKey) - }) t.Run("CreateStarkNetKey", func(tt *testing.T) { diff --git a/core/config/toml/types.go b/core/config/toml/types.go index ba74528b3b6..e3e49dbb18b 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -501,7 +501,6 @@ func (p *AuditLogger) SetFrom(f *AuditLogger) { if v := f.Headers; v != nil { p.Headers = v } - } // LogLevel replaces dpanic with crit/CRIT @@ -882,7 +881,6 @@ func (j *JobPipeline) setFrom(f *JobPipeline) { j.VerboseLogging = v } j.HTTPRequest.setFrom(&f.HTTPRequest) - } type JobPipelineHTTPRequest struct { @@ -1110,7 +1108,6 @@ func (k *Keeper) setFrom(f *Keeper) { } k.Registry.setFrom(&f.Registry) - } type KeeperRegistry struct { diff --git a/core/gethwrappers/versions.go b/core/gethwrappers/versions.go index 43a59ddbb75..2d21f3d0618 100644 --- a/core/gethwrappers/versions.go +++ b/core/gethwrappers/versions.go @@ -51,7 +51,6 @@ func versionsDBLineReader() (*bufio.Scanner, error) { return nil, pkgerrors.Wrapf(err, "could not open versions database") } return bufio.NewScanner(versionsDBFile), nil - } // ReadVersionsDB populates an IntegratedVersion with all the info in the diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 58cedbb96e1..ca9c1bdfcd5 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -341,7 +341,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn case UseRealExternalInitiatorManager: externalInitiatorManager = webhook.NewExternalInitiatorManager(ds, clhttptest.NewTestLocalOnlyHTTPClient()) } - } } @@ -411,7 +410,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn TOMLConfigs: cfg.StarknetConfigs(), } initOps = append(initOps, chainlink.InitStarknet(testCtx, relayerFactory, starkCfg)) - } relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) if err != nil { @@ -1017,7 +1015,6 @@ func HeadWithHash(n int64, hash common.Hash) *evmtypes.Head { time := uint64(0) h = evmtypes.NewHead(big.NewInt(n), hash, evmutils.NewHash(), time, ubig.New(&FixtureChainID)) return &h - } // LegacyTransactionsFromGasPrices returns transactions matching the given gas prices diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go index 36d10981962..2d7c0afc20a 100644 --- a/core/internal/cltest/mocks.go +++ b/core/internal/cltest/mocks.go @@ -410,7 +410,6 @@ func NewLegacyChainsWithMockChain(t testing.TB, ethClient evmclient.Client, cfg ch.On("Config").Return(scopedCfg) return NewLegacyChainsWithChain(ch, cfg) - } func NewLegacyChainsWithMockChainAndTxManager(t testing.TB, ethClient evmclient.Client, cfg legacyevm.AppConfig, txm txmgr.TxManager) legacyevm.LegacyChainContainer { diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 276dea2ac5d..d435252089a 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -53,7 +53,6 @@ func NewChainScopedConfig(t testing.TB, cfg legacyevm.AppConfig) evmconfig.Chain } return evmconfig.NewTOMLChainScopedConfig(evmCfg, logger.TestLogger(t)) - } type TestChainOpts struct { diff --git a/core/logger/audit/audit_logger.go b/core/logger/audit/audit_logger.go index 2f96c40586f..02cee24b0b2 100644 --- a/core/logger/audit/audit_logger.go +++ b/core/logger/audit/audit_logger.go @@ -251,7 +251,6 @@ func (l *AuditLoggerService) postLogToLogService(eventID EventID, data Data) { } l.logger.Errorw("error sending log to HTTP log service", "statusCode", resp.StatusCode, "bodyString", string(bodyBytes)) return - } } diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go index 1f56eb14080..29a8f5bc9e2 100644 --- a/core/scripts/chaincli/handler/keeper.go +++ b/core/scripts/chaincli/handler/keeper.go @@ -246,7 +246,6 @@ func (k *Keeper) VerifyContract(params ...string) { fmt.Println("Running command to verify contract: ", command) if err := k.runCommand(command); err != nil { log.Println("Contract verification on Explorer failed: ", err) - } } diff --git a/core/scripts/chaincli/handler/ocr2_config.go b/core/scripts/chaincli/handler/ocr2_config.go index caa96112ea8..438b96466d0 100644 --- a/core/scripts/chaincli/handler/ocr2_config.go +++ b/core/scripts/chaincli/handler/ocr2_config.go @@ -20,7 +20,6 @@ import ( ) func OCR2GetConfig(hdlr *baseHandler, registry_addr string) error { - b, err := common.ParseHexOrString(registry_addr) if err != nil { return fmt.Errorf("failed to parse address hash: %s", err) diff --git a/core/scripts/chaincli/handler/report.go b/core/scripts/chaincli/handler/report.go index 1dcbb21ee83..eb4ce5c83ac 100644 --- a/core/scripts/chaincli/handler/report.go +++ b/core/scripts/chaincli/handler/report.go @@ -250,7 +250,6 @@ func (t *OCR2Transaction) To() *common.Address { } func (t *OCR2Transaction) From() (common.Address, error) { - switch t.tx.Type() { case 2: from, err := types.Sender(types.NewLondonSigner(t.tx.ChainId()), &t.tx) @@ -296,7 +295,6 @@ type OCR2TransmitTx struct { } func (t *OCR2TransmitTx) UpkeepsInTransmit() ([]ocr2keepers20.UpkeepResult, error) { - txData := t.tx.Data() // recover Method from signature and ABI @@ -367,7 +365,6 @@ func (t *OCR2TransmitTx) SetStaticValues(elem *OCR2ReportDataElem) { } func (t *OCR2TransmitTx) BatchElem() (rpc.BatchElem, error) { - bn, err := t.BlockNumber() if err != nil { return rpc.BatchElem{}, err diff --git a/core/scripts/common/helpers.go b/core/scripts/common/helpers.go index 0967991e62b..a71222e8749 100644 --- a/core/scripts/common/helpers.go +++ b/core/scripts/common/helpers.go @@ -462,7 +462,6 @@ func BinarySearch(top, bottom *big.Int, test func(amount *big.Int) bool) *big.In // Makes RPC network call eth_getBlockByNumber to blockchain RPC node // to fetch header info func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks bool) (headers [][]byte, hashes []string, err error) { - hashes = make([]string, 0) offset := big.NewInt(0) @@ -513,7 +512,6 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo hashes = append(hashes, h.Hash().String()) } else if IsPolygonEdgeNetwork(env.ChainID) { - // Get child block since it's the one that has the parent hash in its header. nextBlockNum := new(big.Int).Set(blockNum).Add(blockNum, offset) var hash string @@ -523,7 +521,6 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo } hashes = append(hashes, hash) - } else { // Get child block since it's the one that has the parent hash in its header. h, err2 := env.Ec.HeaderByNumber( diff --git a/core/scripts/common/helpers_test.go b/core/scripts/common/helpers_test.go index 4ca0823d811..54c5a59b3ec 100644 --- a/core/scripts/common/helpers_test.go +++ b/core/scripts/common/helpers_test.go @@ -53,7 +53,6 @@ func TestBinarySearch(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - testFunc := func(val *big.Int) bool { return val.Cmp(big.NewInt(test.result)) < 1 } diff --git a/core/scripts/common/vrf/setup-envs/main.go b/core/scripts/common/vrf/setup-envs/main.go index 55a2cb5c3c2..a5198f8abbe 100644 --- a/core/scripts/common/vrf/setup-envs/main.go +++ b/core/scripts/common/vrf/setup-envs/main.go @@ -52,7 +52,6 @@ var ( ) func main() { - vrfPrimaryNodeURL := flag.String("vrf-primary-node-url", "", "remote node URL") vrfBackupNodeURL := flag.String("vrf-backup-node-url", "", "remote node URL") bhsNodeURL := flag.String("bhs-node-url", "", "remote node URL") @@ -198,7 +197,6 @@ func main() { importVRFKeyToNodeIfSet(vrfBackupNodeURL, nodesMap, output, nodesMap[model.VRFBackupNodeName].CredsFile) if *deployContractsAndCreateJobs { - contractAddresses := model.ContractAddresses{ LinkAddress: *linkAddress, LinkEthAddress: *linkEthAddress, diff --git a/core/scripts/functions/src/fetch_keys.go b/core/scripts/functions/src/fetch_keys.go index 4c3b11a7e28..265bd152290 100644 --- a/core/scripts/functions/src/fetch_keys.go +++ b/core/scripts/functions/src/fetch_keys.go @@ -40,5 +40,4 @@ func (g *fetchKeys) Run(args []string) { panic(err) } fmt.Println("Functions OCR2 public keys have been saved to:", filepath) - } diff --git a/core/scripts/functions/src/files_test.go b/core/scripts/functions/src/files_test.go index 4f6c5aeb24c..83ceb5cd9cc 100644 --- a/core/scripts/functions/src/files_test.go +++ b/core/scripts/functions/src/files_test.go @@ -31,7 +31,6 @@ func Test_writeLines(t *testing.T) { got, err := readLines(pth) assert.NoError(t, err) assert.Equal(t, tt.args.lines, got) - }) } } diff --git a/core/scripts/ocr2vrf/setup_ocr2vrf.go b/core/scripts/ocr2vrf/setup_ocr2vrf.go index 1094b823b4e..35d529b0262 100644 --- a/core/scripts/ocr2vrf/setup_ocr2vrf.go +++ b/core/scripts/ocr2vrf/setup_ocr2vrf.go @@ -214,7 +214,6 @@ func setupOCR2VRFNodes(e helpers.Environment) { if *useForwarder { fmt.Println("Setting authorized senders...") for i, f := range forwarderAddresses { - // Convert the sending strings for a transmitter to addresses. var sendinKeysAddresses []common.Address sendingKeysStrings := sendingKeys[i+1] diff --git a/core/scripts/vrfv2plus/testnet/proofs.go b/core/scripts/vrfv2plus/testnet/proofs.go index ef35fd3e0ec..23ddc8ecfd6 100644 --- a/core/scripts/vrfv2plus/testnet/proofs.go +++ b/core/scripts/vrfv2plus/testnet/proofs.go @@ -54,7 +54,6 @@ var rcTemplate = `{ ` func generateProofForV2Plus(e helpers.Environment) { - deployCmd := flag.NewFlagSet("generate-proof", flag.ExitOnError) keyHashString := deployCmd.String("key-hash", "", "key hash for VRF request") diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go index 3c5109f82c1..2181084aeec 100644 --- a/core/services/blockhashstore/delegate.go +++ b/core/services/blockhashstore/delegate.go @@ -116,7 +116,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c *v1.VRFCoordinator if c, err = v1.NewVRFCoordinator( jb.BlockhashStoreSpec.CoordinatorV1Address.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V1 coordinator") } @@ -131,7 +130,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c *v2.VRFCoordinatorV2 if c, err = v2.NewVRFCoordinatorV2( jb.BlockhashStoreSpec.CoordinatorV2Address.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V2 coordinator") } @@ -146,7 +144,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c v2plus.IVRFCoordinatorV2PlusInternalInterface if c, err = v2plus.NewIVRFCoordinatorV2PlusInternal( jb.BlockhashStoreSpec.CoordinatorV2PlusAddress.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V2Plus coordinator") } diff --git a/core/services/blockheaderfeeder/delegate.go b/core/services/blockheaderfeeder/delegate.go index d848ba7c61e..36d1d1cf895 100644 --- a/core/services/blockheaderfeeder/delegate.go +++ b/core/services/blockheaderfeeder/delegate.go @@ -114,7 +114,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c *v1.VRFCoordinator if c, err = v1.NewVRFCoordinator( jb.BlockHeaderFeederSpec.CoordinatorV1Address.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V1 coordinator") } var coord *blockhashstore.V1Coordinator @@ -128,7 +127,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c *v2.VRFCoordinatorV2 if c, err = v2.NewVRFCoordinatorV2( jb.BlockHeaderFeederSpec.CoordinatorV2Address.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V2 coordinator") } var coord *blockhashstore.V2Coordinator @@ -142,7 +140,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi var c v2plus.IVRFCoordinatorV2PlusInternalInterface if c, err = v2plus.NewIVRFCoordinatorV2PlusInternal( jb.BlockHeaderFeederSpec.CoordinatorV2PlusAddress.Address(), chain.Client()); err != nil { - return nil, errors.Wrap(err, "building V2 plus coordinator") } var coord *blockhashstore.V2PlusCoordinator diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go index 444f34abcbb..29393ee0fdd 100644 --- a/core/services/chainlink/config_general_test.go +++ b/core/services/chainlink/config_general_test.go @@ -114,7 +114,6 @@ func TestValidateDB(t *testing.T) { require.Error(t, err) require.ErrorIs(t, err, ErrInvalidSecrets) }) - } func TestConfig_LogSQL(t *testing.T) { diff --git a/core/services/chainlink/config_p2p.go b/core/services/chainlink/config_p2p.go index 4197358b148..5f1b9b88141 100644 --- a/core/services/chainlink/config_p2p.go +++ b/core/services/chainlink/config_p2p.go @@ -69,7 +69,6 @@ func (v *p2pv2) DeltaDial() commonconfig.Duration { func (v *p2pv2) DeltaReconcile() commonconfig.Duration { if d := v.c.DeltaReconcile; d != nil { return *d - } return commonconfig.Duration{} } diff --git a/core/services/chainlink/config_pyroscope_test.go b/core/services/chainlink/config_pyroscope_test.go index fc1f7788e0c..33078f41621 100644 --- a/core/services/chainlink/config_pyroscope_test.go +++ b/core/services/chainlink/config_pyroscope_test.go @@ -19,5 +19,4 @@ func TestPyroscopeConfigTest(t *testing.T) { require.Equal(t, "pyroscope-token", pcfg.AuthToken()) require.Equal(t, "http://localhost:4040", pcfg.ServerAddress()) require.Equal(t, "tests", pcfg.Environment()) - } diff --git a/core/services/chainlink/config_web_server_test.go b/core/services/chainlink/config_web_server_test.go index 946e0b0c12b..d96e6c05d5e 100644 --- a/core/services/chainlink/config_web_server_test.go +++ b/core/services/chainlink/config_web_server_test.go @@ -45,5 +45,4 @@ func TestWebServerConfig(t *testing.T) { mf := ws.MFA() assert.Equal(t, "test-rpid", mf.RPID()) assert.Equal(t, "test-rp-origin", mf.RPOrigin()) - } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 3ed3c3242ba..32bcc9f18a4 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -212,7 +212,6 @@ func (rs *CoreRelayerChainInteroperators) LegacyCosmosChains() LegacyCosmosConta // ChainStatus gets [types.ChainStatus] func (rs *CoreRelayerChainInteroperators) ChainStatus(ctx context.Context, id types.RelayID) (types.ChainStatus, error) { - lr, err := rs.Get(id) if err != nil { return types.ChainStatus{}, fmt.Errorf("%w: error getting chain status: %w", chains.ErrNotFound, err) @@ -222,7 +221,6 @@ func (rs *CoreRelayerChainInteroperators) ChainStatus(ctx context.Context, id ty } func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]types.ChainStatus, int, error) { - var ( stats []types.ChainStatus totalErr error @@ -332,7 +330,6 @@ func FilterRelayersByType(network string) func(id types.RelayID) bool { // A typical usage pattern to use [List] with [FilterByType] to obtain a set of [RelayerChainInteroperators] // for a given chain func (rs *CoreRelayerChainInteroperators) List(filter FilterFn) RelayerChainInteroperators { - matches := make(map[types.RelayID]loop.Relayer) rs.mu.Lock() for id, relayer := range rs.loopRelayers { diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 8111c1f61b4..c6183cc1a34 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -33,14 +33,12 @@ import ( ) func TestCoreRelayerChainInteroperators(t *testing.T) { - evmChainID1, evmChainID2 := ubig.New(big.NewInt(1)), ubig.New(big.NewInt(2)) solanaChainID1, solanaChainID2 := "solana-id-1", "solana-id-2" starknetChainID1, starknetChainID2 := "starknet-id-1", "starknet-id-2" cosmosChainID1, cosmosChainID2 := "cosmos-id-1", "cosmos-id-2" cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - cfg := evmcfg.Defaults(evmChainID1) node1_1 := evmcfg.Node{ Name: ptr("Test node chain1:1"), @@ -403,7 +401,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { assert.NoError(t, err) assert.Len(t, nodesStats, expectedNodeCnt) assert.Equal(t, cnt, len(nodesStats)) - } assert.EqualValues(t, gotRelayerNetworks, tt.expectedRelayerNetworks) @@ -442,9 +439,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { unwanted, err := cr.Get(expectedMissing) assert.Nil(t, unwanted) assert.ErrorIs(t, err, chainlink.ErrNoSuchRelayer) - }) - } t.Run("bad init func", func(t *testing.T) { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 8bb06538f03..0e08ed5b420 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -102,7 +102,6 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solana.TOMLConf unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: types.NetworkSolana, ChainID: *chainCfg.ChainID} _, alreadyExists := unique[relayID.Name()] if alreadyExists { @@ -119,7 +118,6 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solana.TOMLConf lggr := solLggr.Named(relayID.ChainID) if cmdName := env.SolanaPlugin.Cmd.Get(); cmdName != "" { - // setup the solana relayer to be a LOOP cfgTOML, err := toml.Marshal(struct { Solana solana.TOMLConfig @@ -142,7 +140,6 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solana.TOMLConf } solanaRelayers[relayID] = loop.NewRelayerService(lggr, r.GRPCOpts, solCmdFn, string(cfgTOML), signer) - } else { // fallback to embedded chain opts := solana.ChainOpts{ @@ -233,7 +230,6 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML } } return starknetRelayers, nil - } type CosmosFactoryConfig struct { @@ -290,8 +286,6 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI } relayers[relayID] = NewCosmosLoopRelayerChain(cosmos.NewRelayer(lggr, chain), chain) - } return relayers, nil - } diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index d6032befbdc..e185fbc8c39 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -1050,7 +1050,6 @@ func (s *service) observeJobProposalCounts(ctx context.Context) error { // Set the prometheus gauge metrics. for _, status := range []JobProposalStatus{JobProposalStatusPending, JobProposalStatusApproved, JobProposalStatusCancelled, JobProposalStatusRejected, JobProposalStatusDeleted, JobProposalStatusRevoked} { - status := status promJobProposalCounts.With(prometheus.Labels{"status": string(status)}).Set(metrics[status]) @@ -1131,7 +1130,6 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error js, err = fluxmonitorv2.ValidatedFluxMonitorSpec(s.jobCfg, spec) default: return nil, errors.Errorf("unknown job type: %s", jobType) - } if err != nil { return nil, err diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go index dd30156e15e..31db95f2626 100644 --- a/core/services/fluxmonitorv2/flux_monitor.go +++ b/core/services/fluxmonitorv2/flux_monitor.go @@ -461,7 +461,6 @@ func formatTime(at time.Time) string { // SetOracleAddress sets the oracle address which matches the node's keys. // If none match, it uses the first available key func (fm *FluxMonitor) SetOracleAddress() error { - // fm on deprecation path, using dangling context ctx, cancel := fm.chStop.NewCtx() defer cancel() diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 6b9dcb99262..2dacac54281 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -376,7 +376,6 @@ func assertNoSubmission(t *testing.T, duration time.Duration, msg string, ) { - // drain the channel for len(submissionReceived) > 0 { <-submissionReceived diff --git a/core/services/fluxmonitorv2/orm.go b/core/services/fluxmonitorv2/orm.go index e090b84ed04..2f7411d1190 100644 --- a/core/services/fluxmonitorv2/orm.go +++ b/core/services/fluxmonitorv2/orm.go @@ -120,7 +120,6 @@ func (o *orm) CreateEthTransaction( gasLimit uint64, idempotencyKey *string, ) (err error) { - _, err = o.txm.CreateTransaction(ctx, txmgr.TxRequest{ IdempotencyKey: idempotencyKey, FromAddress: fromAddress, diff --git a/core/services/fluxmonitorv2/poll_manager.go b/core/services/fluxmonitorv2/poll_manager.go index 356ce96aaea..78b99aec4d5 100644 --- a/core/services/fluxmonitorv2/poll_manager.go +++ b/core/services/fluxmonitorv2/poll_manager.go @@ -260,7 +260,6 @@ func (pm *PollManager) startPollTicker() { // startIdleTimer starts the idle timer if it is enabled func (pm *PollManager) startIdleTimer(roundStartedAtUTC uint64) { - if pm.cfg.IdleTimerDisabled { pm.idleTimer.Stop() diff --git a/core/services/fluxmonitorv2/poll_manager_test.go b/core/services/fluxmonitorv2/poll_manager_test.go index be6aa9a819b..610e05000e2 100644 --- a/core/services/fluxmonitorv2/poll_manager_test.go +++ b/core/services/fluxmonitorv2/poll_manager_test.go @@ -343,7 +343,6 @@ func TestPollManager_ShouldPerformInitialPoll(t *testing.T) { assert.Equal(t, tc.want, pm.ShouldPerformInitialPoll()) }) - } } diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go index aadc84ba96a..7e1f3ced34f 100644 --- a/core/services/functions/connector_handler_test.go +++ b/core/services/functions/connector_handler_test.go @@ -130,7 +130,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":true,"rows":[{"slot_id":1,"version":1,"expiration":1},{"slot_id":2,"version":2,"expiration":2}]}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -142,7 +141,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":false,"error_message":"Failed to list secrets: boom"}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -187,7 +185,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":true}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -200,7 +197,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":false,"error_message":"Failed to set secret: boom"}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -216,7 +212,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":false,"error_message":"Failed to set secret: wrong signature"}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -231,7 +226,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":false,"error_message":"Bad request to set secret: invalid character 's' looking for beginning of object key string"}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) @@ -244,7 +238,6 @@ func TestFunctionsConnectorHandler(t *testing.T) { msg, ok := args[2].(*api.Message) require.True(t, ok) require.Equal(t, `{"success":false,"error_message":"user subscription has insufficient balance"}`, string(msg.Body.Payload)) - }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", &msg) diff --git a/core/services/functions/external_adapter_client_test.go b/core/services/functions/external_adapter_client_test.go index 4ce78ee3fc3..aab969a5050 100644 --- a/core/services/functions/external_adapter_client_test.go +++ b/core/services/functions/external_adapter_client_test.go @@ -215,7 +215,6 @@ func TestRunComputation_ContextRespected(t *testing.T) { } func TestRunComputationRetrial(t *testing.T) { - t.Run("OK-retry_succeeds_after_one_failure", func(t *testing.T) { counter := 0 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/core/services/functions/orm_test.go b/core/services/functions/orm_test.go index 37b3a28256f..859781dada7 100644 --- a/core/services/functions/orm_test.go +++ b/core/services/functions/orm_test.go @@ -258,7 +258,6 @@ func TestORM_FindOldestEntriesByState(t *testing.T) { require.Equal(t, defaultGasLimit, *result[0].CallbackGasLimit) require.Equal(t, defaultCoordinatorContract, *result[0].CoordinatorContractAddress) require.Equal(t, defaultMetadata, result[0].OnchainMetadata) - }) t.Run("with no limit", func(t *testing.T) { diff --git a/core/services/gateway/handlers/functions/allowlist/allowlist_test.go b/core/services/gateway/handlers/functions/allowlist/allowlist_test.go index d4900627bdb..500985acc31 100644 --- a/core/services/gateway/handlers/functions/allowlist/allowlist_test.go +++ b/core/services/gateway/handlers/functions/allowlist/allowlist_test.go @@ -314,11 +314,9 @@ func TestUpdateFromContract(t *testing.T) { return allowlist.Allow(common.HexToAddress(addr1)) && !allowlist.Allow(common.HexToAddress(addr3)) }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) }) - } func TestExtractContractVersion(t *testing.T) { - type tc struct { name string versionStr string diff --git a/core/services/job/kv_orm.go b/core/services/job/kv_orm.go index 63384efc25b..ba2b8d5f9ab 100644 --- a/core/services/job/kv_orm.go +++ b/core/services/job/kv_orm.go @@ -36,7 +36,6 @@ func NewKVStore(jobID int32, ds sqlutil.DataSource, lggr logger.Logger) kVStore // Store saves []byte value by key. func (kv kVStore) Store(ctx context.Context, key string, val []byte) error { - sql := `INSERT INTO job_kv_store (job_id, key, val_bytea) VALUES ($1, $2, $3) ON CONFLICT (job_id, key) DO UPDATE SET diff --git a/core/services/job/models.go b/core/services/job/models.go index 3d510efa0d2..578e9e079b8 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -404,7 +404,6 @@ func (s *OCR2OracleSpec) getChainID() (string, error) { } func (s *OCR2OracleSpec) getChainIdFromRelayConfig() (string, error) { - v, exists := s.RelayConfig["chainID"] if !exists { return "", fmt.Errorf("chainID does not exist") diff --git a/core/services/job/orm.go b/core/services/job/orm.go index d87b0204263..d54d6fba522 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -1121,7 +1121,6 @@ func (o *orm) loadPipelineRunIDs(ctx context.Context, jobID *int32, offset, limi return } lggr.Debugw("loadPipelineRunIDs empty batch", "minId", minID, "maxID", maxID, "n", n, "len(ids)", len(ids), "limit", limit, "offset", offset, "skipped", skipped) - } } maxID = minID - 1 diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index cdfe39dd17f..0232fbadd9f 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -555,7 +555,6 @@ answer1 [type=median index=0]; } for _, tc := range testCases { - config = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go index 6bb2cdbf76b..f7cd5e2bcb3 100644 --- a/core/services/job/spawner.go +++ b/core/services/job/spawner.go @@ -107,7 +107,6 @@ func (js *spawner) Start(ctx context.Context) error { return js.StartOnce("JobSpawner", func() error { js.startAllServices(ctx) return nil - }) } @@ -116,7 +115,6 @@ func (js *spawner) Close() error { close(js.chStop) js.stopAllServices() return nil - }) } diff --git a/core/services/keeper/validate_test.go b/core/services/keeper/validate_test.go index 598bc3da4ed..cfa6a1520f5 100644 --- a/core/services/keeper/validate_test.go +++ b/core/services/keeper/validate_test.go @@ -192,5 +192,4 @@ func TestValidatedKeeperSpec(t *testing.T) { require.Equal(t, tt.want.updatedAt, got.KeeperSpec.UpdatedAt) }) } - } diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 4a9c8a952ff..b27ec54956b 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -305,7 +305,6 @@ func Test_EthKeyStore_GetRoundRobinAddress(t *testing.T) { } { - // k2 and k4 are disabled address for SimulatedChainID so even though it's whitelisted, it will be ignored addresses := []common.Address{k4.Address, k3.Address, k1.Address, k2.Address, testutils.NewAddress()} diff --git a/core/services/keystore/keys/exportutils.go b/core/services/keystore/keys/exportutils.go index 5d75b5076e6..c8209bf5c4f 100644 --- a/core/services/keystore/keys/exportutils.go +++ b/core/services/keystore/keys/exportutils.go @@ -32,7 +32,6 @@ func FromEncryptedJSON[E Encrypted, K any]( passwordFunc func(string) string, privKeyToKey func(export E, rawPrivKey []byte) (K, error), ) (K, error) { - // unmarshal byte data to [E] Encrypted key export var export E if err := json.Unmarshal(keyJSON, &export); err != nil { @@ -64,7 +63,6 @@ func ToEncryptedJSON[E Encrypted, K any]( passwordFunc func(string) string, buildExport func(id string, key K, cryptoJSON keystore.CryptoJSON) E, ) (export []byte, err error) { - // encrypt data using prefixed password cryptoJSON, err := keystore.EncryptDataV3( raw, diff --git a/core/services/keystore/keys/vrfkey/public_key_test.go b/core/services/keystore/keys/vrfkey/public_key_test.go index dec6ae1a56a..70c26ae27fe 100644 --- a/core/services/keystore/keys/vrfkey/public_key_test.go +++ b/core/services/keystore/keys/vrfkey/public_key_test.go @@ -33,7 +33,6 @@ func TestValueScanIdentityPointSet(t *testing.T) { assert.Equal(t, pk, nnPk, "setting one PubliKey to another should result in equal keys") } - } // Tests that PublicKey.Hash gives the same result as the VRFCoordinator's diff --git a/core/services/keystore/models_test.go b/core/services/keystore/models_test.go index 93c0f5fcb25..25331a3b218 100644 --- a/core/services/keystore/models_test.go +++ b/core/services/keystore/models_test.go @@ -167,5 +167,4 @@ func TestKeyRing_Encrypt_Decrypt(t *testing.T) { _, err = originalKeyRing.LegacyKeys.UnloadUnsupported(nil) require.Error(t, err) }) - } diff --git a/core/services/keystore/ocr2_test.go b/core/services/keystore/ocr2_test.go index f2c8715ab4f..7288b86d1d1 100644 --- a/core/services/keystore/ocr2_test.go +++ b/core/services/keystore/ocr2_test.go @@ -61,7 +61,6 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { created := map[chaintype.ChainType]bool{} for _, chain := range chaintype.SupportedChainTypes { - // validate no keys exist for chain keys, err := ks.GetAllOfType(chain) require.NoError(t, err) diff --git a/core/services/keystore/starknet.go b/core/services/keystore/starknet.go index e6655a4d3f2..19f8ccb7b3f 100644 --- a/core/services/keystore/starknet.go +++ b/core/services/keystore/starknet.go @@ -168,7 +168,6 @@ var _ loop.Keystore = &StarknetLooppSigner{} // the returned []byte is an encoded [github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/starknet.Signature]. // this enables compatibility with [github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/txm.NewKeystoreAdapter] func (lk *StarknetLooppSigner) Sign(ctx context.Context, id string, hash []byte) ([]byte, error) { - k, err := lk.Get(id) if err != nil { return nil, err diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go index 97d4219272b..aa610124531 100644 --- a/core/services/keystore/starknet_test.go +++ b/core/services/keystore/starknet_test.go @@ -139,7 +139,6 @@ func TestStarknetSigner(t *testing.T) { // TODO BCF-2242 remove this test once we have starknet smoke/integration tests // that exercise the transaction signing. t.Run("keystore adapter integration", func(t *testing.T) { - adapter := starktxm.NewKeystoreAdapter(lk) baseKs.On("Get", starknetSenderAddr).Return(starkKey, nil) hash, err := curve.Curve.PedersenHash([]*big.Int{big.NewInt(42)}) diff --git a/core/services/llo/orm_test.go b/core/services/llo/orm_test.go index 63a6ac21e3b..a25a1bdea2f 100644 --- a/core/services/llo/orm_test.go +++ b/core/services/llo/orm_test.go @@ -30,7 +30,6 @@ func Test_ORM(t *testing.T) { assert.Zero(t, cd) assert.Zero(t, blockNum) - }) t.Run("loads channel definitions from database", func(t *testing.T) { expectedBlockNum := rand.Int63() diff --git a/core/services/nurse.go b/core/services/nurse.go index 1b44beea21c..a9069b5181d 100644 --- a/core/services/nurse.go +++ b/core/services/nurse.go @@ -318,7 +318,6 @@ func (n *Nurse) gatherCPU(now time.Time, wg *sync.WaitGroup) { n.log.Errorw("could not close cpu profile", "err", err) return } - } func (n *Nurse) gatherTrace(now time.Time, wg *sync.WaitGroup) { @@ -485,5 +484,4 @@ func (n *Nurse) listProfiles() ([]fs.FileInfo, error) { out = append(out, info) } return out, nil - } diff --git a/core/services/nurse_test.go b/core/services/nurse_test.go index 7521168aa3f..4597eeb456b 100644 --- a/core/services/nurse_test.go +++ b/core/services/nurse_test.go @@ -98,7 +98,6 @@ func (c mockConfig) GoroutineThreshold() int { } func TestNurse(t *testing.T) { - l := logger.TestLogger(t) nrse := NewNurse(newMockConfig(t), l) nrse.AddCheck("test", func() (bool, Meta) { return true, Meta{} }) diff --git a/core/services/ocr/config_overrider.go b/core/services/ocr/config_overrider.go index a58cb402695..435efa437c7 100644 --- a/core/services/ocr/config_overrider.go +++ b/core/services/ocr/config_overrider.go @@ -53,7 +53,6 @@ func NewConfigOverriderImpl( flags *ContractFlags, pollTicker utils.TickerBase, ) (*ConfigOverriderImpl, error) { - if !flags.ContractExists() { return nil, errors.Errorf("OCRConfigOverrider: Flags contract instance is missing, the contract does not exist: %s. "+ "Please create the contract or remove the OCR.TransmitterAddress configuration variable", contractAddress.Address()) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 7747cad3360..1addae25601 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -1426,7 +1426,6 @@ func (d *Delegate) newServicesOCR2Keepers20( cfg ocr2keeper.PluginConfig, spec *job.OCR2OracleSpec, ) ([]job.ServiceCtx, error) { - rid, err := spec.RelayID() if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keepers2.0"} diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index bae1f5f3e78..720ad308348 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -169,7 +169,6 @@ func TestGetEVMEffectiveTransmitterID(t *testing.T) { if !jb.ForwardingAllowed { require.Equal(t, jb.OCR2OracleSpec.TransmitterID.String, effectiveTransmitterID) } - }) } diff --git a/core/services/ocr2/plugins/generic/relayerset.go b/core/services/ocr2/plugins/generic/relayerset.go index 0586f600c50..229166dd36a 100644 --- a/core/services/ocr2/plugins/generic/relayerset.go +++ b/core/services/ocr2/plugins/generic/relayerset.go @@ -20,7 +20,6 @@ type RelayerSet struct { } func NewRelayerSet(relayGetter RelayGetter, externalJobID uuid.UUID, jobID int32, isNew bool) (*RelayerSet, error) { - wrappedRelayers := map[types.RelayID]core.Relayer{} relayers, err := relayGetter.GetIDToRelayerMap() @@ -44,7 +43,6 @@ func (r *RelayerSet) Get(_ context.Context, id types.RelayID) (core.Relayer, err } func (r *RelayerSet) List(_ context.Context, relayIDs ...types.RelayID) (map[types.RelayID]core.Relayer, error) { - if len(relayIDs) == 0 { return r.wrappedRelayers, nil } @@ -72,7 +70,6 @@ type relayerWrapper struct { } func (r relayerWrapper) NewPluginProvider(ctx context.Context, rargs core.RelayArgs, pargs core.PluginArgs) (types.PluginProvider, error) { - relayArgs := types.RelayArgs{ ExternalJobID: r.ExternalJobID, JobID: r.JobID, diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go index 9aef7e29d78..021a15c6eff 100644 --- a/core/services/ocr2/plugins/generic/relayerset_test.go +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -15,7 +15,6 @@ import ( ) func TestRelayerSet_List(t *testing.T) { - testRelayersMap := map[types.RelayID]loop.Relayer{} testRelayersMap[types.RelayID{Network: "N1", ChainID: "C1"}] = &TestRelayer{} testRelayersMap[types.RelayID{Network: "N2", ChainID: "C2"}] = &TestRelayer{} @@ -43,7 +42,6 @@ func TestRelayerSet_List(t *testing.T) { } func TestRelayerSet_Get(t *testing.T) { - testRelayersMap := map[types.RelayID]loop.Relayer{} testRelayersMap[types.RelayID{Network: "N1", ChainID: "C1"}] = &TestRelayer{} testRelayersMap[types.RelayID{Network: "N2", ChainID: "C2"}] = &TestRelayer{} diff --git a/core/services/ocr2/plugins/llo/config/config.go b/core/services/ocr2/plugins/llo/config/config.go index 15bb5e816a8..1a6e528980b 100644 --- a/core/services/ocr2/plugins/llo/config/config.go +++ b/core/services/ocr2/plugins/llo/config/config.go @@ -99,7 +99,6 @@ func validateKeyBundleIDs(keyBundleIDs map[string]string) error { if !chaintype.IsSupportedChainType(chaintype.ChainType(k)) { return fmt.Errorf("llo: KeyBundleIDs: key must be a supported chain type, got: %s", k) } - } return nil } diff --git a/core/services/ocr2/plugins/mercury/config/config_test.go b/core/services/ocr2/plugins/mercury/config/config_test.go index cc7c6a82e36..5beba287133 100644 --- a/core/services/ocr2/plugins/mercury/config/config_test.go +++ b/core/services/ocr2/plugins/mercury/config/config_test.go @@ -134,7 +134,6 @@ func Test_PluginConfig(t *testing.T) { require.NotNil(t, mc.NativeFeedID) assert.Equal(t, "0x00026b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472", (*mc.LinkFeedID).String()) assert.Equal(t, "0x00036b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472", (*mc.NativeFeedID).String()) - }) t.Run("with invalid values", func(t *testing.T) { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/abi_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/abi_test.go index c63c0d00f33..7bbbf4d7e32 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/abi_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/abi_test.go @@ -37,7 +37,6 @@ func TestUnpackTransmitTxInput(t *testing.T) { } func TestUnpackTransmitTxInputErrors(t *testing.T) { - tests := []struct { Name string RawData string diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/encoder_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/encoder_test.go index 76212892657..f77b823bb36 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/encoder_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/encoder_test.go @@ -218,5 +218,4 @@ func TestEVMAutomationEncoder20(t *testing.T) { assert.Errorf(t, err, "pack failed: failed to pack report data") assert.Len(t, b, 0) }) - } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go index 9fc2d7891f2..da4dd17d96f 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go @@ -399,7 +399,6 @@ func (r *EvmRegistry) registerEvents(chainID uint64, addr common.Address) error } func (r *EvmRegistry) processUpkeepStateLog(l logpoller.Log) error { - hash := l.TxHash.String() if _, ok := r.txHashes[hash]; ok { return nil diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go index 8108f1a3466..46314dde418 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go @@ -239,7 +239,6 @@ func TestIntegration_LogEventProvider_Backfill(t *testing.T) { for _, tc := range tests { bufferVersion, limitLow := tc.bufferVersion, tc.logLimit t.Run(tc.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(testutils.Context(t), time.Second*60) defer cancel() diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go index e2c1a1531e2..633188c8396 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go @@ -167,7 +167,6 @@ func (p *logEventProvider) WithBufferVersion(v BufferVersion) { func (p *logEventProvider) Start(context.Context) error { return p.StartOnce(LogProviderServiceName, func() error { - readQ := make(chan []*big.Int, readJobQueueSize) p.lggr.Infow("starting log event provider", "readInterval", p.opts.ReadInterval, "readMaxBatchSize", readMaxBatchSize, "readers", readerThreads) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go index 57da895403e..c5bc047e8f4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go @@ -288,7 +288,6 @@ func TestLogEventProvider_ReadLogs(t *testing.T) { }) // TODO: test rate limiting - } func newEntry(p *logEventProvider, i int, args ...string) (LogTriggerConfig, upkeepFilter) { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/services.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/services.go index 5fe21b08724..8cdcd53ade3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/services.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/services.go @@ -12,7 +12,6 @@ type AutomationServices interface { } func New(keyring ocrtypes.OnchainKeyring) (AutomationServices, error) { - services := new(automationServices) services.keyring = NewOnchainKeyringV3Wrapper(keyring) diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 1054c59dd1c..29e56460c36 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -427,7 +427,6 @@ func setupForwarderForNode( backend *backends.SimulatedBackend, recipient common.Address, linkAddr common.Address) common.Address { - faddr, _, authorizedForwarder, err := authorized_forwarder.DeployAuthorizedForwarder(caller, backend, linkAddr, caller.From, recipient, []byte{}) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go index e7688556124..1cb2d613d31 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go @@ -479,7 +479,6 @@ func (c *coordinator) getBlockhashesMappingFromRequests( currentHeight uint64, recentBlockHashesStartHeight uint64, ) (blockhashesMapping map[uint64]common.Hash, err error) { - // Get all request + callback requests into a mapping. rawBlocksRequested := make(map[uint64]struct{}) for _, l := range randomnessRequestedLogs { @@ -586,7 +585,6 @@ func (c *coordinator) filterUnfulfilledCallbacks( currentHeight uint64, currentBatchGasLimit int64, ) (callbacks []ocr2vrftypes.AbstractCostedCallbackRequest) { - /** * Callback batch ordering: * - Callbacks are first ordered by beacon output + confirmation delay (ascending), in other words @@ -663,7 +661,6 @@ func (c *coordinator) filterEligibleCallbacks( currentHeight uint64, blockhashesMapping map[uint64]common.Hash, ) (callbacks []*vrf_wrapper.VRFCoordinatorRandomnessFulfillmentRequested, unfulfilled []block, err error) { - for _, r := range randomnessFulfillmentRequestedLogs { // The on-chain machinery will revert requests that specify an unsupported // confirmation delay, so this is more of a sanity check than anything else. @@ -711,7 +708,6 @@ func (c *coordinator) filterEligibleRandomnessRequests( currentHeight uint64, blockhashesMapping map[uint64]common.Hash, ) (unfulfilled []block, err error) { - for _, r := range randomnessRequestedLogs { // The on-chain machinery will revert requests that specify an unsupported // confirmation delay, so this is more of a sanity check than anything else. diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go index beee01eaf7a..e5913b0a844 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go @@ -1298,7 +1298,6 @@ func TestCoordinator_ReportIsOnchain(t *testing.T) { assert.NoError(t, err) assert.False(t, present) }) - } func TestCoordinator_ConfirmationDelays(t *testing.T) { diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache.go index bd249c6bc27..0dab659258e 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache.go @@ -27,7 +27,6 @@ type cacheItem[T any] struct { // NewBlockCache constructs a new cache. func NewBlockCache[T any](evictionWindow time.Duration) *ocrCache[T] { - // Construct cache cleaner to evict old items. cleaner := &intervalCacheCleaner[T]{ interval: evictionWindow, @@ -50,7 +49,6 @@ func NewBlockCache[T any](evictionWindow time.Duration) *ocrCache[T] { // AddItem adds an item to the cache. func (l *ocrCache[T]) CacheItem(item T, itemKey common.Hash, timeStored time.Time) { - // Construct new item to be stored. newItem := &cacheItem[T]{ item: item, @@ -72,7 +70,6 @@ func (l *ocrCache[T]) SetEvictonWindow(newWindow time.Duration) { // AddItem adds an item to the cache. func (l *ocrCache[T]) GetItem(itemKey common.Hash) (item *T) { - // Lock, and defer unlock. l.cacheMu.Lock() defer l.cacheMu.Unlock() @@ -90,7 +87,6 @@ func (l *ocrCache[T]) GetItem(itemKey common.Hash) (item *T) { // EvictExpiredItems removes all expired items stored in the cache. func (l *ocrCache[T]) EvictExpiredItems(currentTime time.Time) { - // Lock, and defer unlock. l.cacheMu.Lock() defer l.cacheMu.Unlock() diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache_test.go index 57aaf1c5e03..b4be43420b4 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/ocr_cache_test.go @@ -16,7 +16,6 @@ func TestNewCache(t *testing.T) { func TestCache(t *testing.T) { t.Run("Happy path, no overwrites.", func(t *testing.T) { - now := time.Now().UTC() tests := []struct { @@ -65,7 +64,6 @@ func TestCache(t *testing.T) { }) t.Run("Happy path, override middle item.", func(t *testing.T) { - now := time.Now().UTC() tests := []struct { @@ -105,7 +103,6 @@ func TestCache(t *testing.T) { }) t.Run("Happy path, override last item.", func(t *testing.T) { - now := time.Now().UTC() tests := []struct { diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index 2e1e15fd058..8087591a123 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -713,7 +713,6 @@ linkEthFeedAddress = "%s" // First arg is the request ID, which starts at zero, second is the index into // the random words. gomega.NewWithT(t).Eventually(func() bool { - var errs []error rw1, err2 := uni.consumer.SReceivedRandomnessByRequestID(nil, redemptionRequestID, big.NewInt(0)) t.Logf("TestRedeemRandomness 1st word err: %+v", err2) diff --git a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go index e4112b55438..b33c749589f 100644 --- a/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go +++ b/core/services/ocr2/plugins/ocr2vrf/reportserializer/report_serializer.go @@ -25,7 +25,6 @@ func NewReportSerializer(encryptionGroup kyber.Group) types.ReportSerializer { // SerializeReport serializes an abstract report into abi-encoded bytes. func (serializer *reportSerializer) SerializeReport(r types.AbstractReport) ([]byte, error) { - packed, err := serializer.e.SerializeReport(r) if err != nil { diff --git a/core/services/ocr2/plugins/s4/plugin_test.go b/core/services/ocr2/plugins/s4/plugin_test.go index 6321b8ce867..12fac8a070b 100644 --- a/core/services/ocr2/plugins/s4/plugin_test.go +++ b/core/services/ocr2/plugins/s4/plugin_test.go @@ -219,7 +219,6 @@ func TestPlugin_ShouldAcceptFinalizedReport(t *testing.T) { assert.False(t, should) assert.Equal(t, 10, len(ormRows)) compareRows(t, rows, ormRows) - }) t.Run("error", func(t *testing.T) { diff --git a/core/services/ocrcommon/adapters_test.go b/core/services/ocrcommon/adapters_test.go index 6c13ac85f15..669e015e7bc 100644 --- a/core/services/ocrcommon/adapters_test.go +++ b/core/services/ocrcommon/adapters_test.go @@ -111,7 +111,6 @@ type fakeContractTransmitter struct { } func (f fakeContractTransmitter) Transmit(ctx context.Context, rc ocrtypes.ReportContext, report ocrtypes.Report, s []ocrtypes.AttributedOnchainSignature) error { - if !reflect.DeepEqual(report, rwi.Report) { return fmt.Errorf("expected Report %v but got %v", rwi.Report, report) } diff --git a/core/services/ocrcommon/block_translator_test.go b/core/services/ocrcommon/block_translator_test.go index dd900681592..cd80c73898f 100644 --- a/core/services/ocrcommon/block_translator_test.go +++ b/core/services/ocrcommon/block_translator_test.go @@ -34,7 +34,6 @@ func Test_BlockTranslator(t *testing.T) { from, to := bt.NumberToQueryRange(ctx, 42) assert.Equal(t, big.NewInt(42), from) assert.Equal(t, big.NewInt(42), to) - }) t.Run("for arbitrum, returns the ArbitrumBlockTranslator", func(t *testing.T) { diff --git a/core/services/ocrcommon/data_source.go b/core/services/ocrcommon/data_source.go index cb544e01639..336074f81f8 100644 --- a/core/services/ocrcommon/data_source.go +++ b/core/services/ocrcommon/data_source.go @@ -384,7 +384,6 @@ func (ds *inMemoryDataSourceCache) Observe(ctx context.Context, timestamp ocr2ty if time.Since(ds.latestTrrs.GetTaskRunResultsFinishedAt()) >= ds.stalenessAlertThreshold { ds.lggr.Errorf("in memory cache is old and hasn't been updated for over %v, latestUpdateErr is: %v", ds.stalenessAlertThreshold, ds.latestUpdateErr) } - } return ds.parse(latestResult) } diff --git a/core/services/ocrcommon/data_source_test.go b/core/services/ocrcommon/data_source_test.go index a62852eaced..1626976b5be 100644 --- a/core/services/ocrcommon/data_source_test.go +++ b/core/services/ocrcommon/data_source_test.go @@ -190,7 +190,6 @@ func Test_InMemoryDataSourceWithProm(t *testing.T) { assert.Equal(t, jsonParseTaskValue, val.String()) // returns expected value after pipeline run assert.Equal(t, cast.ToFloat64(jsonParseTaskValue), promtestutil.ToFloat64(ocrcommon.PromOcrMedianValues)) assert.Equal(t, cast.ToFloat64(jsonParseTaskValue), promtestutil.ToFloat64(ocrcommon.PromBridgeJsonParseValues)) - } type mockSaver struct { diff --git a/core/services/ocrcommon/discoverer_database_test.go b/core/services/ocrcommon/discoverer_database_test.go index 23d5ad661a4..30fb02a8265 100644 --- a/core/services/ocrcommon/discoverer_database_test.go +++ b/core/services/ocrcommon/discoverer_database_test.go @@ -80,7 +80,6 @@ func Test_DiscovererDatabase(t *testing.T) { require.NoError(t, err) assert.Len(t, announcements, 1) assert.Equal(t, []byte{4, 5, 6}, announcements["remote1"]) - }) } diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go index a47ed19ec56..8c4f26cdc03 100644 --- a/core/services/ocrcommon/peer_wrapper_test.go +++ b/core/services/ocrcommon/peer_wrapper_test.go @@ -128,7 +128,6 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { } c.P2P.V2.ListenAddresses = ptr(p2paddresses) c.P2P.V2.AnnounceAddresses = ptr(p2paddresses) - }) pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index e7a59622d97..f764e7380f8 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -177,7 +177,6 @@ func TestParseEATelemetry(t *testing.T) { } func TestGetJsonParsedValue(t *testing.T) { - resp := getJsonParsedValue(trrs[0], &trrs) assert.Equal(t, 123456.123456789, *resp) @@ -187,7 +186,6 @@ func TestGetJsonParsedValue(t *testing.T) { resp = getJsonParsedValue(trrs[1], &trrs) assert.Nil(t, resp) - } func TestSendEATelemetry(t *testing.T) { @@ -303,7 +301,6 @@ func TestGetObservation(t *testing.T) { } obs = e.getObservation(finalResult) assert.Equal(t, obs, int64(123456)) - } func TestCollectAndSend(t *testing.T) { @@ -529,7 +526,6 @@ func TestGetPricesFromResults(t *testing.T) { } func TestShouldCollectEnhancedTelemetryMercury(t *testing.T) { - j := job.Job{ Type: job.Type(pipeline.OffchainReporting2JobType), OCR2OracleSpec: &job.OCR2OracleSpec{ diff --git a/core/services/ocrcommon/transmitter.go b/core/services/ocrcommon/transmitter.go index 423db2316a7..bba54334c97 100644 --- a/core/services/ocrcommon/transmitter.go +++ b/core/services/ocrcommon/transmitter.go @@ -46,7 +46,6 @@ func NewTransmitter( chainID *big.Int, keystore roundRobinKeystore, ) (Transmitter, error) { - // Ensure that a keystore is provided. if keystore == nil { return nil, errors.New("nil keystore provided to transmitter") @@ -65,7 +64,6 @@ func NewTransmitter( } func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error { - roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.fromAddresses...) if err != nil { return errors.Wrap(err, "skipped OCR transmission, error getting round-robin address") diff --git a/core/services/periodicbackup/backup_test.go b/core/services/periodicbackup/backup_test.go index 99581e62720..b9ca9476a06 100644 --- a/core/services/periodicbackup/backup_test.go +++ b/core/services/periodicbackup/backup_test.go @@ -118,7 +118,6 @@ func TestPeriodicBackup_AlternativeOutputDir(t *testing.T) { assert.Greater(t, file.Size(), int64(0)) assert.Contains(t, result.path, "/alternative/cl_backup_0.9.9.dump") - } type testConfig struct { diff --git a/core/services/pg/connection_test.go b/core/services/pg/connection_test.go index b10625a82c9..c4314bfb309 100644 --- a/core/services/pg/connection_test.go +++ b/core/services/pg/connection_test.go @@ -83,5 +83,4 @@ func Test_disallowReplica(t *testing.T) { _, err = db.Exec("SET session_replication_role= 'not_valid_role'") require.Error(t, err) - } diff --git a/core/services/pg/stats.go b/core/services/pg/stats.go index abbc920e0a4..b8b1ed68401 100644 --- a/core/services/pg/stats.go +++ b/core/services/pg/stats.go @@ -91,7 +91,6 @@ func NewStatsReporter(fn StatFn, lggr logger.Logger, opts ...StatsReporterOpt) * } func (r *StatsReporter) Start(ctx context.Context) { - startOnce := func() { r.wg.Add(1) r.lggr.Debug("Starting DB stat reporter") diff --git a/core/services/pg/stats_test.go b/core/services/pg/stats_test.go index 08d4b4221aa..76a8b426fd8 100644 --- a/core/services/pg/stats_test.go +++ b/core/services/pg/stats_test.go @@ -61,7 +61,6 @@ func TestStatReporter(t *testing.T) { {name: "mutli_start", testFn: testMultiStart}, {name: "multi_stop", testFn: testMultiStop}, } { - t.Run(scenario.name, func(t *testing.T) { d := newtestDbStater(t, scenario.name) d.Mock.On("Stats").Return(sql.DBStats{}) diff --git a/core/services/pipeline/common_eth.go b/core/services/pipeline/common_eth.go index d0b11d9006d..b17ca385e50 100644 --- a/core/services/pipeline/common_eth.go +++ b/core/services/pipeline/common_eth.go @@ -195,7 +195,6 @@ func convertToETHABIType(val interface{}, abiType abi.Type) (interface{}, error) case abi.TupleTy: return convertToETHABITuple(abiType, srcVal) - } return nil, errors.Wrapf(ErrBadInput, "cannot convert %v to %v", srcVal.Type(), abiType) } diff --git a/core/services/pipeline/common_http.go b/core/services/pipeline/common_http.go index d787025dc28..492cc8f8f76 100644 --- a/core/services/pipeline/common_http.go +++ b/core/services/pipeline/common_http.go @@ -24,7 +24,6 @@ func makeHTTPRequest( client *http.Client, httpLimit int64, ) ([]byte, int, http.Header, time.Duration, error) { - var bodyReader io.Reader if requestData != nil { bodyBytes, err := json.Marshal(requestData) diff --git a/core/services/pipeline/common_test.go b/core/services/pipeline/common_test.go index f94167d723c..ce545ec14a0 100644 --- a/core/services/pipeline/common_test.go +++ b/core/services/pipeline/common_test.go @@ -319,5 +319,4 @@ func TestGetNextTaskOf(t *testing.T) { nextTask = trrs.GetNextTaskOf(*nextTask) assert.Empty(t, nextTask) - } diff --git a/core/services/pipeline/graph_test.go b/core/services/pipeline/graph_test.go index 2dea29b8b3e..b3960bb1f46 100644 --- a/core/services/pipeline/graph_test.go +++ b/core/services/pipeline/graph_test.go @@ -265,5 +265,4 @@ func TestParse(t *testing.T) { assert.Error(t, err) }) } - } diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go index 0a96a7e08d5..06774e06e99 100644 --- a/core/services/pipeline/orm.go +++ b/core/services/pipeline/orm.go @@ -516,7 +516,6 @@ func (o *orm) insertFinishedRun(ctx context.Context, run *Run, saveSuccessfulTas VALUES (:pipeline_run_id, :id, :type, :index, :output, :error, :dot_id, :created_at, :finished_at);` _, err = o.ds.NamedExecContext(ctx, sql, run.PipelineTaskRuns) return errors.Wrap(err, "failed to insert pipeline_task_runs") - } // DeleteRunsOlderThan deletes all pipeline_runs that have been finished for a certain threshold to free DB space diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 6ff32e15cc7..8c99635c8d1 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -238,7 +238,6 @@ func TestInsertFinishedRuns(t *testing.T) { err = orm.InsertFinishedRuns(ctx, runs, true) require.NoError(t, err) - } func Test_PipelineORM_InsertFinishedRunWithSpec(t *testing.T) { @@ -471,7 +470,6 @@ func Test_PipelineORM_StoreRun_DetectsRestarts(t *testing.T) { ds1 := run.ByDotID("ds1") require.Equal(t, ds1.Output.Val, int64(2)) require.True(t, ds1.FinishedAt.Valid) - } func Test_PipelineORM_StoreRun_UpdateTaskRunResult(t *testing.T) { diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 2de27b3d008..020ac37f28e 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -575,7 +575,6 @@ func (r *runner) ExecuteAndInsertFinishedRun(ctx context.Context, spec Spec, var return 0, trrs, pkgerrors.Wrapf(err, "error inserting finished results for spec ID %v", run.PipelineSpecID) } return run.ID, trrs, nil - } func (r *runner) Run(ctx context.Context, run *Run, l logger.Logger, saveSuccessfulTaskRuns bool, fn func(tx sqlutil.DataSource) error) (incomplete bool, err error) { diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index 44d7acadd27..dddc84e7368 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -607,7 +607,6 @@ func Test_PipelineRunner_AsyncJob_Basic(t *testing.T) { w.Header().Set("X-Chainlink-Pending", "true") response := map[string]interface{}{} require.NoError(t, json.NewEncoder(w).Encode(response)) - }) // 1. Setup bridge @@ -739,7 +738,6 @@ func Test_PipelineRunner_AsyncJob_InstantRestart(t *testing.T) { w.Header().Set("X-Chainlink-Pending", "true") response := map[string]interface{}{} require.NoError(t, json.NewEncoder(w).Encode(response)) - }) // 1. Setup bridge diff --git a/core/services/pipeline/scheduler.go b/core/services/pipeline/scheduler.go index 7663ed948ff..b589c9a7449 100644 --- a/core/services/pipeline/scheduler.go +++ b/core/services/pipeline/scheduler.go @@ -269,7 +269,6 @@ func (s *scheduler) Run() { s.waiting++ } } - } close(s.taskCh) diff --git a/core/services/pipeline/scheduler_test.go b/core/services/pipeline/scheduler_test.go index 1d7da59da9d..eaedfb453a2 100644 --- a/core/services/pipeline/scheduler_test.go +++ b/core/services/pipeline/scheduler_test.go @@ -165,6 +165,5 @@ func TestScheduler(t *testing.T) { } test.assertion(t, *p, s.results) - } } diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go index e95aef4984c..626820a682d 100644 --- a/core/services/pipeline/task.bridge_test.go +++ b/core/services/pipeline/task.bridge_test.go @@ -464,7 +464,6 @@ func TestBridgeTask_AsyncJobPendingState(t *testing.T) { // w.Header().Set("X-Chainlink-Pending", "true") response := map[string]interface{}{"pending": true} require.NoError(t, json.NewEncoder(w).Encode(response)) - }) server := httptest.NewServer(handler) @@ -672,7 +671,6 @@ func TestBridgeTask_Variables(t *testing.T) { if test.expectedErrorContains != "" { require.Contains(t, result.Error.Error(), test.expectedErrorContains) } - } else { require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -942,7 +940,6 @@ func TestAdapterResponse_UnmarshalJSON_Happy(t *testing.T) { } func TestBridgeTask_Headers(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) @@ -983,7 +980,6 @@ func TestBridgeTask_Headers(t *testing.T) { standardHeaders := []string{"Content-Length", "38", "Content-Type", "application/json", "User-Agent", "Go-http-client/1.1"} t.Run("sends headers", func(t *testing.T) { - task := pipeline.BridgeTask{ BaseTask: pipeline.NewBaseTask(0, "bridge", nil, nil, 0), Name: bridge.Name.String(), @@ -1027,7 +1023,6 @@ func TestBridgeTask_Headers(t *testing.T) { }) t.Run("allows to override content-type", func(t *testing.T) { - task := pipeline.BridgeTask{ BaseTask: pipeline.NewBaseTask(0, "bridge", nil, nil, 0), Name: bridge.Name.String(), diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index c38c338df20..5b9beeb43e1 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -72,7 +72,6 @@ func TestETHTxTask(t *testing.T) { pipeline.NewVarsFrom(nil), nil, func(keyStore *keystoremocks.Eth, txManager *txmmocks.MockEvmTxManager) { - data := []byte("foobar") gasLimit := uint64(12345) jobID := int32(321) @@ -394,7 +393,6 @@ func TestETHTxTask(t *testing.T) { }), nil, func(keyStore *keystoremocks.Eth, txManager *txmmocks.MockEvmTxManager) { - keyStore.On("GetRoundRobinAddress", mock.Anything, testutils.FixtureChainID).Return(nil, errors.New("uh oh")) }, nil, pipeline.ErrTaskRunFailed, "while querying keystore", pipeline.RunInfo{IsRetryable: true}, diff --git a/core/services/pipeline/task.http_test.go b/core/services/pipeline/task.http_test.go index 4098ce50d2a..8d1571e6333 100644 --- a/core/services/pipeline/task.http_test.go +++ b/core/services/pipeline/task.http_test.go @@ -192,7 +192,6 @@ func TestHTTPTask_Variables(t *testing.T) { if test.expectedErrorContains != "" { require.Contains(t, result.Error.Error(), test.expectedErrorContains) } - } else { require.NoError(t, result.Error) require.NotNil(t, result.Value) diff --git a/core/services/pipeline/task_object_params.go b/core/services/pipeline/task_object_params.go index 9bcc0d62dc9..8760ede780a 100644 --- a/core/services/pipeline/task_object_params.go +++ b/core/services/pipeline/task_object_params.go @@ -124,7 +124,6 @@ func (o *ObjectParam) UnmarshalPipelineParam(val interface{}) error { o.StringValue = v.StringValue o.DecimalValue = v.DecimalValue return nil - } return fmt.Errorf("bad input for task: %T", val) diff --git a/core/services/pipeline/task_params.go b/core/services/pipeline/task_params.go index 61d3b8650ad..12582f6ef49 100644 --- a/core/services/pipeline/task_params.go +++ b/core/services/pipeline/task_params.go @@ -510,7 +510,6 @@ func (m *MapParam) UnmarshalPipelineParam(val interface{}) error { *m = v.MapValue return nil } - } return errors.Wrapf(ErrBadInput, "expected map, got %T", val) diff --git a/core/services/pipeline/task_params_test.go b/core/services/pipeline/task_params_test.go index 299736cbbc8..88ec0455481 100644 --- a/core/services/pipeline/task_params_test.go +++ b/core/services/pipeline/task_params_test.go @@ -82,7 +82,6 @@ func TestStringSliceParam_UnmarshalPipelineParam(t *testing.T) { } }) } - } func TestBytesParam_UnmarshalPipelineParam(t *testing.T) { diff --git a/core/services/relay/evm/config_poller_test.go b/core/services/relay/evm/config_poller_test.go index 4778c983c9c..8c02c4e2e7e 100644 --- a/core/services/relay/evm/config_poller_test.go +++ b/core/services/relay/evm/config_poller_test.go @@ -387,7 +387,6 @@ func setConfig(t *testing.T, pluginConfig median.OffchainConfig, ocrContract *oc } func addConfig(t *testing.T, user *bind.TransactOpts, configStoreContract *ocrconfigurationstoreevmsimple.OCRConfigurationStoreEVMSimple, config ocrconfigurationstoreevmsimple.OCRConfigurationStoreEVMSimpleConfigurationEVMSimple) { - _, err := configStoreContract.AddConfig(user, config) require.NoError(t, err) } diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 585d20df3ab..81816c34368 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -162,7 +162,6 @@ func (r *Relayer) HealthReport() (report map[string]error) { } func (r *Relayer) NewPluginProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.PluginProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() @@ -256,7 +255,6 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty } func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.LLOProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() @@ -317,7 +315,6 @@ func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes. } func (r *Relayer) NewFunctionsProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.FunctionsProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() @@ -422,7 +419,6 @@ func newConfigWatcher(lggr logger.Logger, replayCtx: replayCtx, replayCancel: replayCancel, } - } func (c *configWatcher) Name() string { diff --git a/core/services/relay/evm/functions/contract_transmitter.go b/core/services/relay/evm/functions/contract_transmitter.go index 4a8ba25fd9d..23143ed3ef1 100644 --- a/core/services/relay/evm/functions/contract_transmitter.go +++ b/core/services/relay/evm/functions/contract_transmitter.go @@ -120,7 +120,6 @@ func NewFunctionsContractTransmitter( } func (oc *contractTransmitter) createEthTransaction(ctx context.Context, toAddress common.Address, payload []byte) error { - roundRobinFromAddress, err := oc.keystore.GetRoundRobinAddress(ctx, oc.chainID, oc.fromAddresses...) if err != nil { return errors.Wrap(err, "skipped OCR transmission, error getting round-robin address") diff --git a/core/services/relay/evm/mercury/orm_test.go b/core/services/relay/evm/mercury/orm_test.go index 2b2e15ffd53..f928acdb538 100644 --- a/core/services/relay/evm/mercury/orm_test.go +++ b/core/services/relay/evm/mercury/orm_test.go @@ -148,7 +148,6 @@ func TestORM(t *testing.T) { transmissions, err = orm.GetTransmitRequests(ctx, sURL2, jobID) require.NoError(t, err) require.Len(t, transmissions, 1) - } func TestORM_PruneTransmitRequests(t *testing.T) { diff --git a/core/services/relay/evm/mercury/wsrpc/pool.go b/core/services/relay/evm/mercury/wsrpc/pool.go index 94c48736f5d..0bd49ddb5ea 100644 --- a/core/services/relay/evm/mercury/wsrpc/pool.go +++ b/core/services/relay/evm/mercury/wsrpc/pool.go @@ -181,7 +181,6 @@ func (p *pool) remove(serverURL string, clientPubKey credentials.StaticSizedPubl if len(p.connections[serverURL]) == 0 { delete(p.connections, serverURL) } - } func (p *pool) newConnection(lggr logger.Logger, clientPrivKey csakey.KeyV2, serverPubKey []byte, serverURL string) *connection { diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index a839ce8430e..d272ce5aa86 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -81,7 +81,6 @@ func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr log } func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go index b83ce0fd81e..3f9fb11bfc9 100644 --- a/core/services/relay/evm/ocr2vrf.go +++ b/core/services/relay/evm/ocr2vrf.go @@ -56,7 +56,6 @@ func NewOCR2VRFRelayer(chain legacyevm.Chain, lggr logger.Logger, ethKeystore ke } func (r *ocr2vrfRelayer) NewDKGProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (DKGProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() @@ -83,7 +82,6 @@ func (r *ocr2vrfRelayer) NewDKGProvider(rargs commontypes.RelayArgs, pargs commo } func (r *ocr2vrfRelayer) NewOCR2VRFProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2VRFProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 ctx := context.Background() diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index 5f49a0b16c9..f262948c9c5 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -139,7 +139,6 @@ func NewChainRelayerExtenders(ctx context.Context, opts legacyevm.ChainRelayExte var result []*ChainRelayerExt var err error for i := range enabled { - cid := enabled[i].ChainID.String() privOpts := legacyevm.ChainRelayExtenderConfig{ Logger: opts.Logger.Named(cid), diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index b9a6433c3a7..f2bc3a33a93 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -66,5 +66,4 @@ func TestChainRelayExtenders(t *testing.T) { s, err := relayExt.GetChainStatus(testutils.Context(t)) assert.NotEmpty(t, s) assert.NoError(t, err) - } diff --git a/core/services/relay/evm/types/size_helper_test.go b/core/services/relay/evm/types/size_helper_test.go index 202269a4536..bdacd4271f5 100644 --- a/core/services/relay/evm/types/size_helper_test.go +++ b/core/services/relay/evm/types/size_helper_test.go @@ -159,7 +159,6 @@ func TestGetMaxSize(t *testing.T) { {big.NewInt(3), true}, } runSizeTest(t, anyNumElements, args, arg1) - }) t.Run("Bytes pack themselves", func(t *testing.T) { @@ -243,7 +242,6 @@ func TestGetMaxSize(t *testing.T) { } func runSizeTest(t *testing.T, n int, args abi.Arguments, params ...any) { - actual, err := types.GetMaxSize(n, args) require.NoError(t, err) diff --git a/core/services/signatures/ethdss/ethdss_test.go b/core/services/signatures/ethdss/ethdss_test.go index e1991147181..014f0f94186 100644 --- a/core/services/signatures/ethdss/ethdss_test.go +++ b/core/services/signatures/ethdss/ethdss_test.go @@ -266,7 +266,6 @@ func _genDistSecret() []*dkg.DistKeyShare { dkss[i] = dks } return dkss - } func genDistSecret(checkValidPublicKey bool) []*dkg.DistKeyShare { diff --git a/core/services/signatures/secp256k1/field_test.go b/core/services/signatures/secp256k1/field_test.go index 463e363e7e4..0914c6390df 100644 --- a/core/services/signatures/secp256k1/field_test.go +++ b/core/services/signatures/secp256k1/field_test.go @@ -109,7 +109,6 @@ func TestField_Clone(t *testing.T) { assert.Equal(t, f, g, "clone output does not equal original") g.Add(f, f) assert.Equal(t, f, h, "clone does not make a copy") - } func TestField_SetBytesAndBytes(t *testing.T) { diff --git a/core/services/synchronization/telemetry_ingress_client.go b/core/services/synchronization/telemetry_ingress_client.go index 75aa3106a8c..dc4ced31d09 100644 --- a/core/services/synchronization/telemetry_ingress_client.go +++ b/core/services/synchronization/telemetry_ingress_client.go @@ -127,7 +127,6 @@ func (tc *telemetryIngressClient) connect(clientPrivKey []byte) { // Wait for close <-tc.chDone - }() } diff --git a/core/services/synchronization/telemetry_ingress_client_test.go b/core/services/synchronization/telemetry_ingress_client_test.go index e7e14eda748..407051ff19b 100644 --- a/core/services/synchronization/telemetry_ingress_client_test.go +++ b/core/services/synchronization/telemetry_ingress_client_test.go @@ -22,7 +22,6 @@ import ( ) func TestTelemetryIngressClient_Send_HappyPath(t *testing.T) { - // Create mocks telemClient := mocks.NewTelemClient(t) csaKeystore := new(ksmocks.CSA) diff --git a/core/services/telemetry/manager.go b/core/services/telemetry/manager.go index 228a997eeca..a65759a5c62 100644 --- a/core/services/telemetry/manager.go +++ b/core/services/telemetry/manager.go @@ -97,7 +97,6 @@ func (m *Manager) HealthReport() map[string]error { // GenMonitoringEndpoint creates a new monitoring endpoints based on the existing available endpoints defined in the core config TOML, if no endpoint for the network and chainID exists, a NOOP agent will be used and the telemetry will not be sent func (m *Manager) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) commontypes.MonitoringEndpoint { - e, found := m.getEndpoint(network, chainID) if !found { @@ -110,7 +109,6 @@ func (m *Manager) GenMonitoringEndpoint(network string, chainID string, contract } return NewIngressAgent(e.client, network, chainID, contractID, telemType) - } func (m *Manager) addEndpoint(e config.TelemetryIngressEndpoint) error { diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go index 9b83ef08234..4e55cb75752 100644 --- a/core/services/telemetry/manager_test.go +++ b/core/services/telemetry/manager_test.go @@ -64,7 +64,6 @@ func TestManagerAgents(t *testing.T) { } func TestNewManager(t *testing.T) { - type endpointTest struct { network string chainID string @@ -181,7 +180,6 @@ func TestNewManager(t *testing.T) { } require.Equal(t, true, found, "cannot find log: %s", e.expectedError) } - } require.Equal(t, "TelemetryManager", m.Name()) @@ -246,7 +244,6 @@ func TestCorrectEndpointRouting(t *testing.T) { Network: e.network, client: clientMock, } - } //Unknown networks or chainID noopEndpoint := tm.GenMonitoringEndpoint("unknown-network", "unknown-chainID", "some-contractID", "some-type") @@ -282,5 +279,4 @@ func TestCorrectEndpointRouting(t *testing.T) { require.Equal(t, telemType, string(clientSent[i].TelemType)) require.Equal(t, []byte(e.chainID), clientSent[i].Telemetry) } - } diff --git a/core/services/vrf/v2/coordinator_v2x_interface.go b/core/services/vrf/v2/coordinator_v2x_interface.go index 9389f12b9f8..31621562588 100644 --- a/core/services/vrf/v2/coordinator_v2x_interface.go +++ b/core/services/vrf/v2/coordinator_v2x_interface.go @@ -157,7 +157,6 @@ func (c *coordinatorV2) Version() vrfcommon.Version { func (c *coordinatorV2) RegisterProvingKey(opts *bind.TransactOpts, oracle *common.Address, publicProvingKey [2]*big.Int, maxGasPrice *uint64) (*types.Transaction, error) { if maxGasPrice != nil { return nil, fmt.Errorf("max gas price not supported for registering proving key in v2") - } return c.coordinator.RegisterProvingKey(opts, *oracle, publicProvingKey) } diff --git a/core/services/vrf/v2/reverted_txns.go b/core/services/vrf/v2/reverted_txns.go index cfd9954a208..846ba347bc7 100644 --- a/core/services/vrf/v2/reverted_txns.go +++ b/core/services/vrf/v2/reverted_txns.go @@ -111,7 +111,6 @@ func (lsn *listenerV2) fetchRecentSingleTxns(ctx context.Context, ds sqlutil.DataSource, chainID uint64, pollPeriod time.Duration) ([]TxnReceiptDB, error) { - // (state = 'confirmed' OR state = 'unconfirmed') sqlQuery := fmt.Sprintf(` WITH already_ff as ( @@ -234,7 +233,6 @@ func (lsn *listenerV2) fetchRevertedForceFulfilmentTxns(ctx context.Context, ds sqlutil.DataSource, chainID uint64, pollPeriod time.Duration) ([]TxnReceiptDB, error) { - sqlQuery := fmt.Sprintf(` WITH txes AS ( SELECT * @@ -416,7 +414,6 @@ func (lsn *listenerV2) postSqlLog(ctx context.Context, begin time.Time, pollPeri func (lsn *listenerV2) filterRevertedTxns(ctx context.Context, recentReceipts []TxnReceiptDB) []RevertedVRFTxn { - revertedVRFTxns := make([]RevertedVRFTxn, 0) for _, txnReceipt := range recentReceipts { switch txnReceipt.ToAddress.Hex() { @@ -471,7 +468,6 @@ func (lsn *listenerV2) filterRevertedTxns(ctx context.Context, func (lsn *listenerV2) filterSingleRevertedTxn(ctx context.Context, txnReceiptDB TxnReceiptDB) ( *RevertedVRFTxn, error) { - requestID := common.HexToHash(txnReceiptDB.RequestID).Big() commitment, err := lsn.coordinator.GetCommitment(&bind.CallOpts{Context: ctx}, requestID) if err != nil { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 212ad37367e..1ad7a3c2ae2 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -474,7 +474,6 @@ func mockAction() (*mockCapability, values.Value) { nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - return capabilities.CapabilityResponse{ Value: outputs, }, nil diff --git a/core/services/workflows/models_yaml_test.go b/core/services/workflows/models_yaml_test.go index efcdaf6f332..5fa326dda5d 100644 --- a/core/services/workflows/models_yaml_test.go +++ b/core/services/workflows/models_yaml_test.go @@ -240,7 +240,6 @@ func TestParsesIntsCorrectly(t *testing.T) { require.NoError(t, err) assert.Equal(t, int64(3600), n.Config["aggregation_config"].(map[string]any)["0x1111111111111111111100000000000000000000000000000000000000000000"].(map[string]any)["heartbeat"]) - } func TestMappingCustomType(t *testing.T) { diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index 8169368eb1f..8a7d1628a4c 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -336,7 +336,6 @@ ON jobs.offchainreporting2_oracle_spec_id = ocr2.id` require.Equal(t, jobIdAndContractId{ID: 30, ContractID: "evm_187246hr3781h9fd198fh391g8f924"}, jobsAndContracts[1]) require.Equal(t, jobIdAndContractId{ID: 10, ContractID: "terra_187246hr3781h9fd198fh391g8f924"}, jobsAndContracts[2]) require.Equal(t, jobIdAndContractId{ID: 20, ContractID: "sol_187246hr3781h9fd198fh391g8f924"}, jobsAndContracts[3]) - } func TestMigrate_101_GenericOCR2(t *testing.T) { @@ -518,7 +517,6 @@ func TestNoTriggers(t *testing.T) { _, db := heavyweight.FullTestDBEmptyV2(t, nil) assert_num_triggers := func(expected int) { - row := db.DB.QueryRow("select count(*) from information_schema.triggers") var count int err := row.Scan(&count) @@ -536,7 +534,6 @@ func TestNoTriggers(t *testing.T) { err := goose.UpTo(db.DB, migrationDir, int64(v)) require.NoError(t, err) assert_num_triggers(1) - } func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { diff --git a/core/store/models/errors.go b/core/store/models/errors.go index 6feddd96c03..d11caa466d5 100644 --- a/core/store/models/errors.go +++ b/core/store/models/errors.go @@ -56,7 +56,6 @@ func (jae *JSONAPIErrors) Merge(e error) { return } jae.Add(e.Error()) - } // CoerceEmptyToNil will return nil if JSONAPIErrors has no errors. diff --git a/core/utils/collection_test.go b/core/utils/collection_test.go index 20bfb2c6261..f956192d3a0 100644 --- a/core/utils/collection_test.go +++ b/core/utils/collection_test.go @@ -53,8 +53,6 @@ func TestBatchSplit(t *testing.T) { } // assert order has not changed when list is reconstructed assert.Equal(t, r.input, temp) - }) } - } diff --git a/core/utils/deferable_write_closer.go b/core/utils/deferable_write_closer.go index e27b6d91d6e..eebea80f822 100644 --- a/core/utils/deferable_write_closer.go +++ b/core/utils/deferable_write_closer.go @@ -49,7 +49,6 @@ func NewDeferableWriteCloser(wc io.WriteCloser) *DeferableWriteCloser { // Should be called explicitly AND defered // Thread safe func (wc *DeferableWriteCloser) Close() error { - wc.mu.Lock() defer wc.mu.Unlock() if !wc.closed { @@ -57,5 +56,4 @@ func (wc *DeferableWriteCloser) Close() error { wc.closed = true } return wc.closeErr - } diff --git a/core/utils/deferable_write_closer_test.go b/core/utils/deferable_write_closer_test.go index d12ff1c40cb..ef03acf9d66 100644 --- a/core/utils/deferable_write_closer_test.go +++ b/core/utils/deferable_write_closer_test.go @@ -10,7 +10,6 @@ import ( ) func TestDeferableWriteCloser_Close(t *testing.T) { - d := t.TempDir() f, err := os.Create(filepath.Join(d, "test-file")) require.NoError(t, err) diff --git a/core/utils/utils.go b/core/utils/utils.go index 78151517c62..d076284112f 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -479,7 +479,6 @@ func NewRedialBackoff() backoff.Backoff { Max: 15 * time.Second, Jitter: true, } - } // KeyedMutex allows to lock based on particular values diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go index c08983ff4b8..587bd46efb9 100644 --- a/core/utils/utils_test.go +++ b/core/utils/utils_test.go @@ -549,5 +549,4 @@ func TestErrorBuffer(t *testing.T) { combined := buff.Flush() require.Nil(t, combined) }) - } diff --git a/core/web/common.go b/core/web/common.go index 66159d8b60a..36c169bc748 100644 --- a/core/web/common.go +++ b/core/web/common.go @@ -16,7 +16,6 @@ var ( ) func getChain(legacyChains legacyevm.LegacyChainContainer, chainIDstr string) (chain legacyevm.Chain, err error) { - if chainIDstr != "" && chainIDstr != "" { // evm keys are expected to be parsable as a big int _, ok := big.NewInt(0).SetString(chainIDstr, 10) diff --git a/core/web/cors_test.go b/core/web/cors_test.go index fcd5d9b3874..c08e11bc125 100644 --- a/core/web/cors_test.go +++ b/core/web/cors_test.go @@ -55,7 +55,6 @@ func TestCors_OverrideOrigins(t *testing.T) { for _, test := range tests { t.Run(test.origin, func(t *testing.T) { - config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.WebServer.AllowOrigins = ptr(test.allow) }) diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go index 9aaa0dd9eeb..2d5eb42515a 100644 --- a/core/web/cosmos_chains_controller_test.go +++ b/core/web/cosmos_chains_controller_test.go @@ -165,7 +165,6 @@ func Test_CosmosChainsController_Index(t *testing.T) { tomlB, err := chainB.TOMLString() require.NoError(t, err) assert.Equal(t, tomlB, chains[0].Config) - } type TestCosmosChainsController struct { diff --git a/core/web/dkgencrypt_keys_controller_test.go b/core/web/dkgencrypt_keys_controller_test.go index fde00eb6420..0f4344fdc23 100644 --- a/core/web/dkgencrypt_keys_controller_test.go +++ b/core/web/dkgencrypt_keys_controller_test.go @@ -93,7 +93,6 @@ func TestDKGEncryptKeysController_Delete_HappyPath(t *testing.T) { afterKeys, err := keyStore.DKGEncrypt().GetAll() assert.NoError(t, err) assert.Equal(t, initialLength-1, len(afterKeys)) - } func setupDKGEncryptKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { diff --git a/core/web/dkgsign_keys_controller_test.go b/core/web/dkgsign_keys_controller_test.go index b253a36ccc3..01b8489c0b8 100644 --- a/core/web/dkgsign_keys_controller_test.go +++ b/core/web/dkgsign_keys_controller_test.go @@ -93,7 +93,6 @@ func TestDKGSignKeysController_Delete_HappyPath(t *testing.T) { afterKeys, err := keyStore.DKGSign().GetAll() assert.NoError(t, err) assert.Equal(t, initialLength-1, len(afterKeys)) - } func setupDKGSignKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { diff --git a/core/web/eth_keys_controller.go b/core/web/eth_keys_controller.go index e53f30a925a..043362ff441 100644 --- a/core/web/eth_keys_controller.go +++ b/core/web/eth_keys_controller.go @@ -115,7 +115,6 @@ func (ekc *ETHKeysController) Index(c *gin.Context) { }) jsonAPIResponseWithStatus(c, resources, "keys", http.StatusOK) - } // Create adds a new account @@ -362,7 +361,6 @@ func (ekc *ETHKeysController) getEthBalance(ctx context.Context, state ethkey.St } return bal - } func (ekc *ETHKeysController) setLinkBalance(bal *commonassets.Link) presenters.NewETHKeyOption { diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index 34cde6f6a64..9cb6a27b434 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -73,11 +73,9 @@ func TestETHKeysController_Index_Success(t *testing.T) { if balance.Address == expectedKeys[0].Address.Hex() { assert.Equal(t, "0.000000000000000256", balance.EthBalance.String()) assert.Equal(t, "256", balance.LinkBalance.String()) - } else { assert.Equal(t, "0.000000000000000001", balance.EthBalance.String()) assert.Equal(t, "1", balance.LinkBalance.String()) - } } } diff --git a/core/web/evm_chains_controller_test.go b/core/web/evm_chains_controller_test.go index 157978bdd46..ab8bf35e6cb 100644 --- a/core/web/evm_chains_controller_test.go +++ b/core/web/evm_chains_controller_test.go @@ -106,7 +106,6 @@ func Test_EVMChainsController_Index(t *testing.T) { // sort test chain ids to make expected comparison easy chainIDs := []*big.Int{testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID()} sort.Slice(chainIDs, func(i, j int) bool { - return chainIDs[i].String() < chainIDs[j].String() }) diff --git a/core/web/evm_forwarders_controller_test.go b/core/web/evm_forwarders_controller_test.go index 38e8c2f91f0..cacab870717 100644 --- a/core/web/evm_forwarders_controller_test.go +++ b/core/web/evm_forwarders_controller_test.go @@ -100,7 +100,6 @@ func Test_EVMForwardersController_Index(t *testing.T) { }, } for _, fwdr := range fwdrs { - body, err := json.Marshal(web.TrackEVMForwarderRequest{ EVMChainID: chainId, Address: fwdr.Address, diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 0146038d91b..8aaae0d5ba3 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -323,7 +323,6 @@ func TestJobController_Create_HappyPath(t *testing.T) { return fmt.Sprintf(testspecs.FluxMonitorSpecTemplate, nameAndExternalJobID, nameAndExternalJobID) }, assertion: func(t *testing.T, nameAndExternalJobID string, r *http.Response) { - require.Equal(t, http.StatusInternalServerError, r.StatusCode) errs := cltest.ParseJSONAPIErrors(t, r.Body) diff --git a/core/web/lca_controller.go b/core/web/lca_controller.go index bb4866c3d08..0c3a065f2fd 100644 --- a/core/web/lca_controller.go +++ b/core/web/lca_controller.go @@ -48,7 +48,6 @@ func (bdc *LCAController) FindLCA(c *gin.Context) { EVMChainID: big.New(chainID), } jsonAPIResponse(c, &response, "response") - } type LCAResponse struct { diff --git a/core/web/log_controller_test.go b/core/web/log_controller_test.go index 28c54b72450..61e75e8bb48 100644 --- a/core/web/log_controller_test.go +++ b/core/web/log_controller_test.go @@ -53,7 +53,6 @@ func TestLogController_GetLogConfig(t *testing.T) { require.Equal(t, "warn", svcLogConfig.DefaultLogLevel) for i, svcName := range svcLogConfig.ServiceName { - if svcName == "Global" { assert.Equal(t, zapcore.WarnLevel.String(), svcLogConfig.LogLevel[i]) } @@ -130,7 +129,6 @@ func TestLogController_PatchLogConfig(t *testing.T) { require.NoError(t, cltest.ParseJSONAPIResponse(t, resp, &svcLogConfig)) for i, svcName := range svcLogConfig.ServiceName { - if svcName == "Global" { assert.Equal(t, tc.expectedLogLevel.String(), svcLogConfig.LogLevel[i]) } diff --git a/core/web/loop_registry.go b/core/web/loop_registry.go index b94778675e0..ffa80146449 100644 --- a/core/web/loop_registry.go +++ b/core/web/loop_registry.go @@ -70,7 +70,6 @@ func (l *LoopRegistryServer) discoveryHandler(w http.ResponseWriter, req *http.R w.WriteHeader(http.StatusInternalServerError) l.logger.Error(err) } - } func metricTarget(hostName string, port int, path string) *targetgroup.Group { diff --git a/core/web/resolver/chain_test.go b/core/web/resolver/chain_test.go index a0f2ca22b07..5e51356d928 100644 --- a/core/web/resolver/chain_test.go +++ b/core/web/resolver/chain_test.go @@ -77,7 +77,6 @@ ResendAfterThreshold = '1h0m0s' name: "success", authenticated: true, before: func(f *gqlTestFramework) { - chainConf := evmtoml.EVMConfig{ ChainID: &chainID, Enabled: chain.Enabled, @@ -94,7 +93,6 @@ ResendAfterThreshold = '1h0m0s' Config: chainConfToml, }}, }}) - }, query: query, result: fmt.Sprintf(` @@ -117,7 +115,6 @@ ResendAfterThreshold = '1h0m0s' authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{}}) - }, query: query, result: ` diff --git a/core/web/resolver/helpers.go b/core/web/resolver/helpers.go index 8c9ac09c943..b2ec3ab0709 100644 --- a/core/web/resolver/helpers.go +++ b/core/web/resolver/helpers.go @@ -83,7 +83,6 @@ func ValidateBridgeType(bt *bridges.BridgeTypeRequest) error { } if bt.MinimumContractPayment != nil && bt.MinimumContractPayment.Cmp(assets.NewLinkFromJuels(0)) < 0 { - return errors.New("MinimumContractPayment must be positive") } diff --git a/core/web/resolver/job_proposal_spec_test.go b/core/web/resolver/job_proposal_spec_test.go index c65702c5622..5875a5acb69 100644 --- a/core/web/resolver/job_proposal_spec_test.go +++ b/core/web/resolver/job_proposal_spec_test.go @@ -160,7 +160,6 @@ func TestResolver_CancelJobProposalSpec(t *testing.T) { f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) - }, query: mutation, variables: variables, @@ -349,7 +348,6 @@ func TestResolver_UpdateJobProposalSpecDefinition(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateSpecDefinition", mock.Anything, specID, "").Return(sql.ErrNoRows) - }, query: mutation, variables: variables, diff --git a/core/web/resolver/node_test.go b/core/web/resolver/node_test.go index 62e964a6820..e103a470097 100644 --- a/core/web/resolver/node_test.go +++ b/core/web/resolver/node_test.go @@ -57,7 +57,6 @@ func TestResolver_Nodes(t *testing.T) { }}, }, }) - }, query: query, result: ` diff --git a/core/web/router.go b/core/web/router.go index 158ea4b411f..9c5cb4b661d 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -228,7 +228,6 @@ func loopRoutes(app chainlink.Application, r *gin.RouterGroup) { loopRegistry := NewLoopRegistryServer(app) r.GET("/discovery", ginHandlerFromHTTP(loopRegistry.discoveryHandler)) r.GET("/plugins/:name/metrics", loopRegistry.pluginMetricHandler) - } func v2Routes(app chainlink.Application, r *gin.RouterGroup) { diff --git a/tools/flakeytests/runner.go b/tools/flakeytests/runner.go index a37b123d5cf..d4c6451a945 100644 --- a/tools/flakeytests/runner.go +++ b/tools/flakeytests/runner.go @@ -232,7 +232,6 @@ func (r *Runner) runTests(rep *Report) (*Report, error) { report.SetTest(pkg, t, 1) } } - } } @@ -292,7 +291,6 @@ func dedupeEntries(report *Report) (*Report, error) { out.SetTest(pkg, tn, report.tests[pkg][tn]) } - } return out, nil From 700a82719451611381ab5dbb94fe00547660440b Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Tue, 7 May 2024 17:56:34 +0700 Subject: [PATCH 27/35] implement remove nodes (#13102) --- .changeset/tiny-rocks-shake.md | 5 + contracts/.changeset/stupid-horses-promise.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 24 +++ .../CapabilityRegistry_RemoveNodesTest.t.sol | 98 ++++++++++++ .../keystone_capability_registry.go | 147 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 .changeset/tiny-rocks-shake.md create mode 100644 contracts/.changeset/stupid-horses-promise.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol diff --git a/.changeset/tiny-rocks-shake.md b/.changeset/tiny-rocks-shake.md new file mode 100644 index 00000000000..d6311632f08 --- /dev/null +++ b/.changeset/tiny-rocks-shake.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal generate geth wrappers for capability registry remove nodes diff --git a/contracts/.changeset/stupid-horses-promise.md b/contracts/.changeset/stupid-horses-promise.md new file mode 100644 index 00000000000..b7de55939d8 --- /dev/null +++ b/contracts/.changeset/stupid-horses-promise.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +implement remove nodes on capability registry diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 6ac4caedf50..60989fce61a 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -106,6 +106,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param nodeOperatorId The ID of the node operator that manages this node event NodeAdded(bytes32 p2pId, uint256 nodeOperatorId); + /// @notice This event is emitted when a node is removed + /// @param p2pId The P2P ID of the node that was removed + event NodeRemoved(bytes32 p2pId); + /// @notice This event is emitted when a node is updated /// @param p2pId The P2P ID of the node /// @param nodeOperatorId The ID of the node operator that manages this node @@ -269,6 +273,26 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } } + /// @notice Removes nodes. The node operator admin or contract owner + /// can remove nodes + /// @param removedNodeP2PIds The P2P Ids of the nodes to remove + function removeNodes(bytes32[] calldata removedNodeP2PIds) external { + bool isOwner = msg.sender == owner(); + for (uint256 i; i < removedNodeP2PIds.length; ++i) { + bytes32 p2pId = removedNodeP2PIds[i]; + Node memory node = s_nodes[p2pId]; + + bool nodeExists = s_nodes[p2pId].supportedHashedCapabilityIds.length > 0; + if (!nodeExists) revert InvalidNodeP2PId(p2pId); + + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; + + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(); + delete s_nodes[p2pId]; + emit NodeRemoved(p2pId); + } + } + /// @notice Updates nodes. The node admin can update the node's signer address /// and reconfigure its supported capabilities /// @param nodes The nodes to update diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol new file mode 100644 index 00000000000..d432a8aed04 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_RemoveNodesTest is BaseTest { + event NodeRemoved(bytes32 p2pId); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + bytes32 private constant INVALID_P2P_ID = bytes32("fake-p2p"); + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); + s_capabilityRegistry.removeNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = INVALID_P2P_ID; + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, INVALID_P2P_ID)); + s_capabilityRegistry.removeNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = bytes32(""); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_capabilityRegistry.removeNodes(nodes); + } + + function test_RemovesNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeRemoved(P2P_ID); + s_capabilityRegistry.removeNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, address(0)); + assertEq(node.supportedHashedCapabilityIds.length, 0); + } + + function test_OwnerCanRemoveNodes() public { + changePrank(ADMIN); + + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeRemoved(P2P_ID); + s_capabilityRegistry.removeNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, address(0)); + assertEq(node.supportedHashedCapabilityIds.length, 0); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 9080fbd7807..afa4dd13812 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -50,8 +50,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6125e680620001606000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806365c14dc7116100b2578063ae3c241c11610081578063c2d483a111610066578063c2d483a1146102d3578063ddbe4f82146102e6578063f2fde38b146102fb57600080fd5b8063ae3c241c146102ad578063b38e51f6146102c057600080fd5b806365c14dc71461023d57806379ba50971461025d5780638da5cb5b146102655780639cb7c5f41461028d57600080fd5b80631cdf6343116100ee5780631cdf6343146101af57806336b402fb146101c2578063398f37731461020a57806350c946fe1461021d57600080fd5b80630c5801e314610120578063117392ce146101355780631257001114610148578063181f5a7714610170575b600080fd5b61013361012e366004611b8d565b61030e565b005b610133610143366004611bf9565b61061f565b61015b610156366004611c11565b61086a565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101679190611c8e565b6101336101bd366004611ca1565b61087d565b6101fc6101d0366004611ce3565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610167565b610133610218366004611ca1565b610940565b61023061022b366004611c11565b610ad9565b6040516101679190611d05565b61025061024b366004611c11565b610ba1565b6040516101679190611d8b565b610133610c7e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610167565b6102a061029b366004611c11565b610d7b565b6040516101679190611e6d565b6101336102bb366004611c11565b610e25565b6101336102ce366004611ca1565b610ef0565b6101336102e1366004611ca1565b61130c565b6102ee6116ed565b6040516101679190611e7b565b610133610309366004611eeb565b611832565b828114610356576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561061757600086868381811061038e5761038e611f08565b90506020020135905060008585848181106103ab576103ab611f08565b90506020028101906103bd9190611f37565b6103c69061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff16610417576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061045457503373ffffffffffffffffffffffffffffffffffffffff851614155b1561048b576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061053d57506020808201516040516104d19201611c8e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600086815260078352929092209192610524926001019101612158565b6040516020818303038152906040528051906020012014155b15610604578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906105aa9082612247565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105fb929190612361565b60405180910390a25b505080610610906123a9565b9050610372565b505050505050565b610627611846565b60408051823560208281019190915280840135828401528251808303840181526060909201909252805191012061065f6003826118c9565b15610696576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106a86080840160608501611eeb565b73ffffffffffffffffffffffffffffffffffffffff1614610813576106d36080830160608401611eeb565b73ffffffffffffffffffffffffffffffffffffffff163b15806107b357506107016080830160608401611eeb565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b191906123e1565b155b15610813576107c86080830160608401611eeb565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161034d565b61081e6003826118e4565b50600081815260026020526040902082906108398282612403565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b60006108776005836118c9565b92915050565b610885611846565b60005b8181101561093b5760008383838181106108a4576108a4611f08565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108f56001830182611aa7565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610934816123a9565b9050610888565b505050565b610948611846565b60005b8181101561093b57600083838381811061096757610967611f08565b90506020028101906109799190611f37565b6109829061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff166109d3576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a569082612247565b50905050600960008154610a69906123a9565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610abe91859190612361565b60405180910390a2505080610ad2906123a9565b905061094b565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b9157602002820191906000526020600020905b815481526020019060010190808311610b7d575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bfe9061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2a9061210b565b8015610b915780601f10610c4c57610100808354040283529160200191610b91565b820191906000526020600020905b815481529060010190602001808311610c5a57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161034d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610de457610de4611dce565b6001811115610df557610df5611dce565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610e2d611846565b610e386003826118c9565b610e71576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610e7c6005826118c9565b15610eb6576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610ec16005826118e4565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561093b576000838383818110610f0f57610f0f611f08565b9050602002810190610f219190612485565b610f2a906124b9565b90506000610f4d60005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff90811683526001820180549690911633149650939491939092840191610fa49061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610fd09061210b565b801561101d5780601f10610ff25761010080835404028352916020019161101d565b820191906000526020600020905b81548152906001019060200180831161100057829003601f168201915b50505050508152505090508115801561104d5750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611084576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808401516000908152600890915260409020600301541515806110dd5783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff1661112e576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360600151516000036111735783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611200576111b48560600151828151811061119c5761119c611f08565b602002602001015160036118c990919063ffffffff16565b6111f05784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b6111f9816123a9565b9050611176565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611285926003850192910190611ae1565b509050507f6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e8460200151856000015186604001516040516112ef93929190928352602083019190915273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b60405180910390a15050505080611305906123a9565b9050610ef3565b60005b8181101561093b57600083838381811061132b5761132b611f08565b905060200281019061133d9190612485565b611346906124b9565b9050600061136960005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff908116835260018201805496909116331496509394919390928401916113c09061210b565b80601f01602080910402602001604051908101604052809291908181526020018280546113ec9061210b565b80156114395780601f1061140e57610100808354040283529160200191611439565b820191906000526020600020905b81548152906001019060200180831161141c57829003601f168201915b5050505050815250509050811580156114695750805173ffffffffffffffffffffffffffffffffffffffff163314155b156114a0576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602080840151600090815260089091526040902060030154151580806114c857506020840151155b156115075783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff16611558576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83606001515160000361159d5783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611612576115c68560600151828151811061119c5761119c611f08565b6116025784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b61160b816123a9565b90506115a0565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611697926003850192910190611ae1565b505050602084810151855160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a150505050806116e6906123a9565b905061130f565b606060006116fb60036118f0565b9050600061170960056118fd565b825161171591906125c6565b67ffffffffffffffff81111561172d5761172d611f75565b60405190808252806020026020018201604052801561179d57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161174b5790505b5090506000805b83518110156118295760008482815181106117c1576117c1611f08565b602002602001015190506117df8160056118c990919063ffffffff16565b611818576117ec81610d7b565b8484815181106117fe576117fe611f08565b60200260200101819052508280611814906123a9565b9350505b50611822816123a9565b90506117a4565b50909392505050565b61183a611846565b61184381611907565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161034d565b565b600081815260018301602052604081205415155b9392505050565b60006118dd83836119fc565b606060006118dd83611a4b565b6000610877825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161034d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054611a4357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610877565b506000610877565b606081600001805480602002602001604051908101604052809291908181526020018280548015611a9b57602002820191906000526020600020905b815481526020019060010190808311611a87575b50505050509050919050565b508054611ab39061210b565b6000825580601f10611ac3575050565b601f0160209004906000526020600020908101906118439190611b2c565b828054828255906000526020600020908101928215611b1c579160200282015b82811115611b1c578251825591602001919060010190611b01565b50611b28929150611b2c565b5090565b5b80821115611b285760008155600101611b2d565b60008083601f840112611b5357600080fd5b50813567ffffffffffffffff811115611b6b57600080fd5b6020830191508360208260051b8501011115611b8657600080fd5b9250929050565b60008060008060408587031215611ba357600080fd5b843567ffffffffffffffff80821115611bbb57600080fd5b611bc788838901611b41565b90965094506020870135915080821115611be057600080fd5b50611bed87828801611b41565b95989497509550505050565b600060808284031215611c0b57600080fd5b50919050565b600060208284031215611c2357600080fd5b5035919050565b6000815180845260005b81811015611c5057602081850181015186830182015201611c34565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006118dd6020830184611c2a565b60008060208385031215611cb457600080fd5b823567ffffffffffffffff811115611ccb57600080fd5b611cd785828601611b41565b90969095509350505050565b60008060408385031215611cf657600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b80831015611d805783518252928401926001929092019190840190611d60565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152611dc66060840182611c2a565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110611e47577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108778284611dfd565b6020808252825182820181905260009190848201906040850190845b81811015611ebd57611eaa838551611dfd565b9284019260809290920191600101611e97565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461184357600080fd5b600060208284031215611efd57600080fd5b81356118dd81611ec9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611f6b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fc757611fc7611f75565b60405290565b6040516080810167ffffffffffffffff81118282101715611fc757611fc7611f75565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203757612037611f75565b604052919050565b60006040823603121561205157600080fd5b612059611fa4565b823561206481611ec9565b815260208381013567ffffffffffffffff8082111561208257600080fd5b9085019036601f83011261209557600080fd5b8135818111156120a7576120a7611f75565b6120d7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ff0565b915080825236848285010111156120ed57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061211f57607f821691505b602082108103611c0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060208083526000845461216c8161210b565b8084870152604060018084166000811461218d57600181146121c5576121f3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506121f3565b896000528660002060005b858110156121eb5781548b82018601529083019088016121d0565b8a0184019650505b509398975050505050505050565b601f82111561093b57600081815260208120601f850160051c810160208610156122285750805b601f850160051c820191505b8181101561061757828155600101612234565b815167ffffffffffffffff81111561226157612261611f75565b6122758161226f845461210b565b84612201565b602080601f8311600181146122c857600084156122925750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610617565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612315578886015182559484019460019091019084016122f6565b508582101561235157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000611dc66040830184611c2a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123da576123da61237a565b5060010190565b6000602082840312156123f357600080fd5b815180151581146118dd57600080fd5b81358155602082013560018201556002810160408301356002811061242757600080fd5b8154606085013561243781611ec9565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611f6b57600080fd5b6000608082360312156124cb57600080fd5b6124d3611fcd565b823581526020808401358183015260408401356124ef81611ec9565b6040830152606084013567ffffffffffffffff8082111561250f57600080fd5b9085019036601f83011261252257600080fd5b81358181111561253457612534611f75565b8060051b9150612545848301611ff0565b818152918301840191848101903684111561255f57600080fd5b938501935b8385101561257d57843582529385019390850190612564565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611ebd578351835292840192918401916001016125aa565b818103818111156108775761087761237a56fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61293380620001606000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806365c14dc7116100b2578063ae3c241c11610081578063c2d483a111610066578063c2d483a114610301578063ddbe4f8214610314578063f2fde38b1461032957600080fd5b8063ae3c241c146102db578063b38e51f6146102ee57600080fd5b806365c14dc71461026b57806379ba50971461028b5780638da5cb5b146102935780639cb7c5f4146102bb57600080fd5b80631cdf63431161010957806336b402fb116100ee57806336b402fb146101f0578063398f37731461023857806350c946fe1461024b57600080fd5b80631cdf6343146101ca5780632c01a1e8146101dd57600080fd5b80630c5801e31461013b578063117392ce146101505780631257001114610163578063181f5a771461018b575b600080fd5b61014e610149366004611eda565b61033c565b005b61014e61015e366004611f46565b61064d565b610176610171366004611f5e565b610898565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101829190611fdb565b61014e6101d8366004611fee565b6108ab565b61014e6101eb366004611fee565b61096e565b61022a6101fe366004612030565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610182565b61014e610246366004611fee565b610c6f565b61025e610259366004611f5e565b610e08565b6040516101829190612052565b61027e610279366004611f5e565b610ed0565b60405161018291906120d8565b61014e610fad565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6102ce6102c9366004611f5e565b6110aa565b60405161018291906121ba565b61014e6102e9366004611f5e565b611154565b61014e6102fc366004611fee565b61121f565b61014e61030f366004611fee565b61163b565b61031c611a1c565b60405161018291906121c8565b61014e610337366004612238565b611b61565b828114610384576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156106455760008686838181106103bc576103bc612255565b90506020020135905060008585848181106103d9576103d9612255565b90506020028101906103eb9190612284565b6103f49061238c565b805190915073ffffffffffffffffffffffffffffffffffffffff16610445576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061048257503373ffffffffffffffffffffffffffffffffffffffff851614155b156104b9576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061056b57506020808201516040516104ff9201611fdb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926105529260010191016124a5565b6040516020818303038152906040528051906020012014155b15610632578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906105d89082612594565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516106299291906126ae565b60405180910390a25b50508061063e906126f6565b90506103a0565b505050505050565b610655611b75565b60408051823560208281019190915280840135828401528251808303840181526060909201909252805191012061068d600382611bf8565b156106c4576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106d66080840160608501612238565b73ffffffffffffffffffffffffffffffffffffffff1614610841576107016080830160608401612238565b73ffffffffffffffffffffffffffffffffffffffff163b15806107e1575061072f6080830160608401612238565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa1580156107bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107df919061272e565b155b15610841576107f66080830160608401612238565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161037b565b61084c600382611c13565b50600081815260026020526040902082906108678282612750565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b60006108a5600583611bf8565b92915050565b6108b3611b75565b60005b818110156109695760008383838181106108d2576108d2612255565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506109236001830182611dd6565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610962816126f6565b90506108b6565b505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c695760008484838181106109a8576109a8612255565b602090810292909201356000818152600884526040808220815160808101835281548152600182015481880152600282015473ffffffffffffffffffffffffffffffffffffffff16818401526003820180548451818a0281018a0190955280855295985093969095509093606086019391830182828015610a4857602002820191906000526020600020905b815481526020019060010190808311610a34575b50505091909252505050600083815260086020526040902060030154909150151580610aa3576040517f64e2ee920000000000000000000000000000000000000000000000000000000081526004810184905260240161037b565b815160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549293919291840191610aef90612458565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1b90612458565b8015610b685780601f10610b3d57610100808354040283529160200191610b68565b820191906000526020600020905b815481529060010190602001808311610b4b57829003601f168201915b505050505081525050905085158015610b985750805173ffffffffffffffffffffffffffffffffffffffff163314155b15610bcf576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600860205260408120818155600181018290556002810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590610c1f6003830182611e10565b50506040518481527f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb97532059060200160405180910390a15050505080610c62906126f6565b905061098c565b50505050565b610c77611b75565b60005b81811015610969576000838383818110610c9657610c96612255565b9050602002810190610ca89190612284565b610cb19061238c565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d02576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610d859082612594565b50905050600960008154610d98906126f6565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610ded918591906126ae565b60405180910390a2505080610e01906126f6565b9050610c7a565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610ec057602002820191906000526020600020905b815481526020019060010190808311610eac575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610f2d90612458565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5990612458565b8015610ec05780601f10610f7b57610100808354040283529160200191610ec0565b820191906000526020600020905b815481529060010190602001808311610f8957505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461102e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161037b565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff16908111156111135761111361211b565b60018111156111245761112461211b565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61115c611b75565b611167600382611bf8565b6111a0576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161037b565b6111ab600582611bf8565b156111e5576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161037b565b6111f0600582611c13565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561096957600083838381811061123e5761123e612255565b905060200281019061125091906127d2565b61125990612806565b9050600061127c60005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff908116835260018201805496909116331496509394919390928401916112d390612458565b80601f01602080910402602001604051908101604052809291908181526020018280546112ff90612458565b801561134c5780601f106113215761010080835404028352916020019161134c565b820191906000526020600020905b81548152906001019060200180831161132f57829003601f168201915b50505050508152505090508115801561137c5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113b3576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208084015160009081526008909152604090206003015415158061140c5783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161037b91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff1661145d576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360600151516000036114a25783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161037b91906128db565b60005b84606001515181101561152f576114e3856060015182815181106114cb576114cb612255565b60200260200101516003611bf890919063ffffffff16565b61151f5784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161037b91906128db565b611528816126f6565b90506114a5565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060860151805187936115b4926003850192910190611e2e565b509050507f6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e84602001518560000151866040015160405161161e93929190928352602083019190915273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b60405180910390a15050505080611634906126f6565b9050611222565b60005b8181101561096957600083838381811061165a5761165a612255565b905060200281019061166c91906127d2565b61167590612806565b9050600061169860005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff908116835260018201805496909116331496509394919390928401916116ef90612458565b80601f016020809104026020016040519081016040528092919081815260200182805461171b90612458565b80156117685780601f1061173d57610100808354040283529160200191611768565b820191906000526020600020905b81548152906001019060200180831161174b57829003601f168201915b5050505050815250509050811580156117985750805173ffffffffffffffffffffffffffffffffffffffff163314155b156117cf576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602080840151600090815260089091526040902060030154151580806117f757506020840151155b156118365783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161037b91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff16611887576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360600151516000036118cc5783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161037b91906128db565b60005b846060015151811015611941576118f5856060015182815181106114cb576114cb612255565b6119315784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161037b91906128db565b61193a816126f6565b90506118cf565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060860151805187936119c6926003850192910190611e2e565b505050602084810151855160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050505080611a15906126f6565b905061163e565b60606000611a2a6003611c1f565b90506000611a386005611c2c565b8251611a449190612913565b67ffffffffffffffff811115611a5c57611a5c6122c2565b604051908082528060200260200182016040528015611acc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611a7a5790505b5090506000805b8351811015611b58576000848281518110611af057611af0612255565b60200260200101519050611b0e816005611bf890919063ffffffff16565b611b4757611b1b816110aa565b848481518110611b2d57611b2d612255565b60200260200101819052508280611b43906126f6565b9350505b50611b51816126f6565b9050611ad3565b50909392505050565b611b69611b75565b611b7281611c36565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161037b565b565b600081815260018301602052604081205415155b9392505050565b6000611c0c8383611d2b565b60606000611c0c83611d7a565b60006108a5825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161037b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054611d72575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108a5565b5060006108a5565b606081600001805480602002602001604051908101604052809291908181526020018280548015611dca57602002820191906000526020600020905b815481526020019060010190808311611db6575b50505050509050919050565b508054611de290612458565b6000825580601f10611df2575050565b601f016020900490600052602060002090810190611b729190611e79565b5080546000825590600052602060002090810190611b729190611e79565b828054828255906000526020600020908101928215611e69579160200282015b82811115611e69578251825591602001919060010190611e4e565b50611e75929150611e79565b5090565b5b80821115611e755760008155600101611e7a565b60008083601f840112611ea057600080fd5b50813567ffffffffffffffff811115611eb857600080fd5b6020830191508360208260051b8501011115611ed357600080fd5b9250929050565b60008060008060408587031215611ef057600080fd5b843567ffffffffffffffff80821115611f0857600080fd5b611f1488838901611e8e565b90965094506020870135915080821115611f2d57600080fd5b50611f3a87828801611e8e565b95989497509550505050565b600060808284031215611f5857600080fd5b50919050565b600060208284031215611f7057600080fd5b5035919050565b6000815180845260005b81811015611f9d57602081850181015186830182015201611f81565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611c0c6020830184611f77565b6000806020838503121561200157600080fd5b823567ffffffffffffffff81111561201857600080fd5b61202485828601611e8e565b90969095509350505050565b6000806040838503121561204357600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156120cd57835182529284019260019290920191908401906120ad565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526121136060840182611f77565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110612194577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108a5828461214a565b6020808252825182820181905260009190848201906040850190845b8181101561220a576121f783855161214a565b92840192608092909201916001016121e4565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7257600080fd5b60006020828403121561224a57600080fd5b8135611c0c81612216565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126122b857600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612314576123146122c2565b60405290565b6040516080810167ffffffffffffffff81118282101715612314576123146122c2565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612384576123846122c2565b604052919050565b60006040823603121561239e57600080fd5b6123a66122f1565b82356123b181612216565b815260208381013567ffffffffffffffff808211156123cf57600080fd5b9085019036601f8301126123e257600080fd5b8135818111156123f4576123f46122c2565b612424847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161233d565b9150808252368482850101111561243a57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061246c57607f821691505b602082108103611f58577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006020808352600084546124b981612458565b808487015260406001808416600081146124da576001811461251257612540565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550612540565b896000528660002060005b858110156125385781548b820186015290830190880161251d565b8a0184019650505b509398975050505050505050565b601f82111561096957600081815260208120601f850160051c810160208610156125755750805b601f850160051c820191505b8181101561064557828155600101612581565b815167ffffffffffffffff8111156125ae576125ae6122c2565b6125c2816125bc8454612458565b8461254e565b602080601f83116001811461261557600084156125df5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610645565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561266257888601518255948401946001909101908401612643565b508582101561269e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006121136040830184611f77565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612727576127276126c7565b5060010190565b60006020828403121561274057600080fd5b81518015158114611c0c57600080fd5b81358155602082013560018201556002810160408301356002811061277457600080fd5b8154606085013561278481612216565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126122b857600080fd5b60006080823603121561281857600080fd5b61282061231a565b8235815260208084013581830152604084013561283c81612216565b6040830152606084013567ffffffffffffffff8082111561285c57600080fd5b9085019036601f83011261286f57600080fd5b813581811115612881576128816122c2565b8060051b915061289284830161233d565b81815291830184019184810190368411156128ac57600080fd5b938501935b838510156128ca578435825293850193908501906128b1565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561220a578351835292840192918401916001016128f7565b818103818111156108a5576108a56126c756fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -438,6 +438,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodeOperat return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "removeNodes", removedNodeP2PIds) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodes(&_CapabilityRegistry.TransactOpts, removedNodeP2PIds) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodes(&_CapabilityRegistry.TransactOpts, removedNodeP2PIds) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -1221,6 +1233,123 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorUpdated( return event, nil } +type CapabilityRegistryNodeRemovedIterator struct { + Event *CapabilityRegistryNodeRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeRemoved struct { + P2pId [32]byte + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeRemovedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeRemoved") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeRemovedIterator{contract: _CapabilityRegistry.contract, event: "NodeRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeRemoved) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeRemoved(log types.Log) (*CapabilityRegistryNodeRemoved, error) { + event := new(CapabilityRegistryNodeRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryNodeUpdatedIterator struct { Event *CapabilityRegistryNodeUpdated @@ -1626,6 +1755,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseNodeOperatorRemoved(log) case _CapabilityRegistry.abi.Events["NodeOperatorUpdated"].ID: return _CapabilityRegistry.ParseNodeOperatorUpdated(log) + case _CapabilityRegistry.abi.Events["NodeRemoved"].ID: + return _CapabilityRegistry.ParseNodeRemoved(log) case _CapabilityRegistry.abi.Events["NodeUpdated"].ID: return _CapabilityRegistry.ParseNodeUpdated(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: @@ -1662,6 +1793,10 @@ func (CapabilityRegistryNodeOperatorUpdated) Topic() common.Hash { return common.HexToHash("0x14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a") } +func (CapabilityRegistryNodeRemoved) Topic() common.Hash { + return common.HexToHash("0x5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb9753205") +} + func (CapabilityRegistryNodeUpdated) Topic() common.Hash { return common.HexToHash("0x6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e") } @@ -1707,6 +1842,8 @@ type CapabilityRegistryInterface interface { RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) + RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) @@ -1749,6 +1886,12 @@ type CapabilityRegistryInterface interface { ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) + FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeRemovedIterator, error) + + WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeRemoved) (event.Subscription, error) + + ParseNodeRemoved(log types.Log) (*CapabilityRegistryNodeRemoved, error) + FilterNodeUpdated(opts *bind.FilterOpts) (*CapabilityRegistryNodeUpdatedIterator, error) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index e2bb9865809..f5b47e58913 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 98d53a1997053a3037827ffd170c12f49d2005a5c266a1ea9eb69bb51e862f37 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 878d2b539e07962af90e8c283fa5a90a15b5b59ddbc0854a137a3be621f0afcd ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From b0b4354e8c9148ba6624df5e9d939972fb7a08b0 Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Tue, 7 May 2024 17:35:42 +0300 Subject: [PATCH 28/35] VRF-330: enabling batch fulfillment for VRF e2e tests (#13091) * VRF-330: enabling batch fulfillment for VRF e2e tests * VRF-330: fixing lint * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: fixing tests * VRF-330: PR comments * VRF-330: PR comments * VRF-330: PR comments --- .github/workflows/integration-tests.yml | 4 +- .../actions/vrf/common/errors.go | 28 +- .../actions/vrf/common/models.go | 21 +- .../actions/vrf/vrfv2/contract_steps.go | 43 ++- integration-tests/actions/vrf/vrfv2/errors.go | 12 +- .../actions/vrf/vrfv2/setup_steps.go | 7 +- .../actions/vrf/vrfv2plus/contract_steps.go | 19 +- .../actions/vrf/vrfv2plus/errors.go | 2 + .../actions/vrf/vrfv2plus/setup_steps.go | 11 +- integration-tests/client/chainlink_models.go | 8 +- .../contracts/contract_deployer.go | 2 + .../contracts/contract_vrf_models.go | 10 + .../contracts/ethereum_ocr2vrf_contracts.go | 19 -- .../contracts/ethereum_vrf_common.go | 24 +- .../contracts/ethereum_vrf_contracts.go | 18 ++ .../contracts/ethereum_vrfv2_contracts.go | 43 +++ .../contracts/ethereum_vrfv2plus_contracts.go | 62 ++++ integration-tests/smoke/vrfv2_test.go | 302 +++++++++++++++++- integration-tests/smoke/vrfv2plus_test.go | 295 ++++++++++++++++- integration-tests/testconfig/vrfv2/vrfv2.toml | 2 +- .../testconfig/vrfv2plus/vrfv2plus.toml | 2 +- 21 files changed, 833 insertions(+), 101 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 8dcf32b127e..10d3e53d619 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -529,12 +529,12 @@ jobs: pyroscope_env: ci-smoke-vrf-evm-simulated - name: vrfv2 id: vrfv2 - nodes: 5 + nodes: 6 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus id: vrfv2plus - nodes: 8 + nodes: 9 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr diff --git a/integration-tests/actions/vrf/common/errors.go b/integration-tests/actions/vrf/common/errors.go index f174609823f..62164d0b274 100644 --- a/integration-tests/actions/vrf/common/errors.go +++ b/integration-tests/actions/vrf/common/errors.go @@ -10,20 +10,20 @@ const ( ErrEncodingProvingKey = "error encoding proving key" ErrDeployBlockHashStore = "error deploying blockhash store" ErrDeployBatchBlockHashStore = "error deploying batch blockhash store" - ErrDeployCoordinator = "error deploying VRF CoordinatorV2" - ErrABIEncodingFunding = "error Abi encoding subscriptionID" - ErrSendingLinkToken = "error sending Link token" - ErrCreatingBHSJob = "error creating BHS job" - ErrParseJob = "error parsing job definition" - ErrSetVRFCoordinatorConfig = "error setting config for VRF Coordinator contract" - ErrCreateVRFSubscription = "error creating VRF Subscription" - ErrAddConsumerToSub = "error adding consumer to VRF Subscription" - ErrFundSubWithLinkToken = "error funding subscription with Link tokens" - ErrRestartCLNode = "error restarting CL node" - ErrWaitTXsComplete = "error waiting for TXs to complete" - ErrRequestRandomness = "error requesting randomness" - ErrLoadingCoordinator = "error loading coordinator contract" - ErrCreatingVRFKey = "error creating VRF key" + + ErrABIEncodingFunding = "error Abi encoding subscriptionID" + ErrSendingLinkToken = "error sending Link token" + ErrCreatingBHSJob = "error creating BHS job" + ErrParseJob = "error parsing job definition" + ErrSetVRFCoordinatorConfig = "error setting config for VRF Coordinator contract" + ErrCreateVRFSubscription = "error creating VRF Subscription" + ErrAddConsumerToSub = "error adding consumer to VRF Subscription" + ErrFundSubWithLinkToken = "error funding subscription with Link tokens" + ErrRestartCLNode = "error restarting CL node" + ErrWaitTXsComplete = "error waiting for TXs to complete" + ErrRequestRandomness = "error requesting randomness" + ErrLoadingCoordinator = "error loading coordinator contract" + ErrCreatingVRFKey = "error creating VRF key" ErrWaitRandomWordsRequestedEvent = "error waiting for RandomWordsRequested event" ErrWaitRandomWordsFulfilledEvent = "error waiting for RandomWordsFulfilled event" diff --git a/integration-tests/actions/vrf/common/models.go b/integration-tests/actions/vrf/common/models.go index d5c1c2b95b0..c88839b4c3b 100644 --- a/integration-tests/actions/vrf/common/models.go +++ b/integration-tests/actions/vrf/common/models.go @@ -43,15 +43,17 @@ type VRFNode struct { } type VRFContracts struct { - CoordinatorV2 contracts.VRFCoordinatorV2 - CoordinatorV2Plus contracts.VRFCoordinatorV2_5 - VRFOwner contracts.VRFOwner - BHS contracts.BlockHashStore - BatchBHS contracts.BatchBlockhashStore - VRFV2Consumers []contracts.VRFv2LoadTestConsumer - VRFV2PlusConsumer []contracts.VRFv2PlusLoadTestConsumer - LinkToken contracts.LinkToken - MockETHLINKFeed contracts.VRFMockETHLINKFeed + CoordinatorV2 contracts.VRFCoordinatorV2 + BatchCoordinatorV2 contracts.BatchVRFCoordinatorV2 + CoordinatorV2Plus contracts.VRFCoordinatorV2_5 + BatchCoordinatorV2Plus contracts.BatchVRFCoordinatorV2Plus + VRFOwner contracts.VRFOwner + BHS contracts.BlockHashStore + BatchBHS contracts.BatchBlockhashStore + VRFV2Consumers []contracts.VRFv2LoadTestConsumer + VRFV2PlusConsumer []contracts.VRFv2PlusLoadTestConsumer + LinkToken contracts.LinkToken + MockETHLINKFeed contracts.VRFMockETHLINKFeed } type VRFOwnerConfig struct { @@ -62,6 +64,7 @@ type VRFOwnerConfig struct { type VRFJobSpecConfig struct { ForwardingAllowed bool CoordinatorAddress string + BatchCoordinatorAddress string FromAddresses []string EVMChainID string MinIncomingConfirmations int diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 7c1ee634f98..495de0dd268 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -51,7 +51,7 @@ func DeployVRFV2Contracts( if useTestCoordinator { testCoordinator, err := env.ContractDeployer.DeployVRFCoordinatorTestV2(linkTokenContract.Address(), bhs.Address(), linkEthFeedContract.Address()) if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployCoordinator, err) + return nil, fmt.Errorf("%s, err %w", ErrDeployCoordinatorV2, err) } err = evmClient.WaitForEvents() if err != nil { @@ -61,7 +61,7 @@ func DeployVRFV2Contracts( } else { coordinator, err := env.ContractDeployer.DeployVRFCoordinatorV2(linkTokenContract.Address(), bhs.Address(), linkEthFeedContract.Address()) if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployCoordinator, err) + return nil, fmt.Errorf("%s, err %w", ErrDeployCoordinatorV2, err) } err = evmClient.WaitForEvents() if err != nil { @@ -74,31 +74,44 @@ func DeployVRFV2Contracts( if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrLoadingCoordinator, err) } + + batchCoordinator, err := env.ContractDeployer.DeployBatchVRFCoordinatorV2(coordinator.Address()) + if err != nil { + return nil, fmt.Errorf("%s, err %w", ErrDeployBatchCoordinatorV2, err) + } + + err = evmClient.WaitForEvents() + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) + } + if useVRFOwner { vrfOwner, err := env.ContractDeployer.DeployVRFOwner(coordinatorAddress) if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployCoordinator, err) + return nil, fmt.Errorf("%s, err %w", ErrDeployCoordinatorV2, err) } err = evmClient.WaitForEvents() if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitTXsComplete, err) } return &vrfcommon.VRFContracts{ - CoordinatorV2: coordinator, - VRFOwner: vrfOwner, - BHS: bhs, - VRFV2Consumers: nil, - LinkToken: linkTokenContract, - MockETHLINKFeed: linkEthFeedContract, + CoordinatorV2: coordinator, + BatchCoordinatorV2: batchCoordinator, + VRFOwner: vrfOwner, + BHS: bhs, + VRFV2Consumers: nil, + LinkToken: linkTokenContract, + MockETHLINKFeed: linkEthFeedContract, }, nil } return &vrfcommon.VRFContracts{ - CoordinatorV2: coordinator, - VRFOwner: nil, - BHS: bhs, - VRFV2Consumers: nil, - LinkToken: linkTokenContract, - MockETHLINKFeed: linkEthFeedContract, + CoordinatorV2: coordinator, + BatchCoordinatorV2: batchCoordinator, + VRFOwner: nil, + BHS: bhs, + VRFV2Consumers: nil, + LinkToken: linkTokenContract, + MockETHLINKFeed: linkEthFeedContract, }, nil } diff --git a/integration-tests/actions/vrf/vrfv2/errors.go b/integration-tests/actions/vrf/vrfv2/errors.go index 3ca94dd630d..dc98270ad4c 100644 --- a/integration-tests/actions/vrf/vrfv2/errors.go +++ b/integration-tests/actions/vrf/vrfv2/errors.go @@ -1,9 +1,11 @@ package vrfv2 const ( - ErrDeployVRFV2Wrapper = "error deploying VRFV2Wrapper" - ErrCreateVRFV2Jobs = "error creating VRF V2 Jobs" - ErrDeployVRFV2Contracts = "error deploying VRFV2 contracts" - ErrCreatingVRFv2Job = "error creating VRFv2 job" - ErrAdvancedConsumer = "error deploying VRFv2 Advanced Consumer" + ErrDeployCoordinatorV2 = "error deploying VRF CoordinatorV2" + ErrDeployBatchCoordinatorV2 = "error deploying Batch VRF CoordinatorV2" + ErrDeployVRFV2Wrapper = "error deploying VRFV2Wrapper" + ErrCreateVRFV2Jobs = "error creating VRF V2 Jobs" + ErrDeployVRFV2Contracts = "error deploying VRFV2 contracts" + ErrCreatingVRFv2Job = "error creating VRFv2 job" + ErrAdvancedConsumer = "error deploying VRFv2 Advanced Consumer" ) diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index ca85bdb5f19..5c441bf811e 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -61,10 +61,8 @@ func CreateVRFV2Job( spec.VRFOwner = vrfJobSpecConfig.VRFOwnerConfig.OwnerAddress spec.UseVRFOwner = true } - - if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrParseJob, err) - + if vrfJobSpecConfig.BatchFulfillmentEnabled { + spec.BatchCoordinatorAddress = vrfJobSpecConfig.BatchCoordinatorAddress } job, err := chainlinkNode.MustCreateJob(spec) if err != nil { @@ -200,6 +198,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, vrfv2Conf vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ ForwardingAllowed: *vrfv2Config.VRFJobForwardingAllowed, CoordinatorAddress: contracts.CoordinatorV2.Address(), + BatchCoordinatorAddress: contracts.BatchCoordinatorV2.Address(), FromAddresses: vrfNode.TXKeyAddressStrings, EVMChainID: chainID.String(), MinIncomingConfirmations: int(*vrfv2Config.MinimumConfirmations), diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 26532e9b8e8..7bd734b1026 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -38,23 +38,28 @@ func DeployVRFV2_5Contracts( if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrDeployBatchBlockHashStore, err) } + coordinator, err := contractDeployer.DeployVRFCoordinatorV2_5(bhs.Address()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployCoordinatorV2Plus, err) + } err = chainClient.WaitForEvents() if err != nil { - return nil, fmt.Errorf("%s, batchBHS err %w", vrfcommon.ErrWaitTXsComplete, err) + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) } - coordinator, err := contractDeployer.DeployVRFCoordinatorV2_5(bhs.Address()) + batchCoordinator, err := contractDeployer.DeployBatchVRFCoordinatorV2Plus(coordinator.Address()) if err != nil { - return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrDeployCoordinator, err) + return nil, fmt.Errorf("%s, err %w", ErrDeployBatchCoordinatorV2Plus, err) } err = chainClient.WaitForEvents() if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) } return &vrfcommon.VRFContracts{ - CoordinatorV2Plus: coordinator, - BHS: bhs, - BatchBHS: batchBHS, - VRFV2PlusConsumer: nil, + CoordinatorV2Plus: coordinator, + BatchCoordinatorV2Plus: batchCoordinator, + BHS: bhs, + BatchBHS: batchBHS, + VRFV2PlusConsumer: nil, }, nil } diff --git a/integration-tests/actions/vrf/vrfv2plus/errors.go b/integration-tests/actions/vrf/vrfv2plus/errors.go index d39e2002c13..250c4da85a7 100644 --- a/integration-tests/actions/vrf/vrfv2plus/errors.go +++ b/integration-tests/actions/vrf/vrfv2plus/errors.go @@ -1,6 +1,8 @@ package vrfv2plus const ( + ErrDeployCoordinatorV2Plus = "error deploying VRF CoordinatorV2Plus" + ErrDeployBatchCoordinatorV2Plus = "error deploying Batch VRF CoordinatorV2Plus" ErrCreatingVRFv2PlusKey = "error creating VRFv2Plus key" ErrAdvancedConsumer = "error deploying VRFv2Plus Advanced Consumer" ErrCreatingVRFv2PlusJob = "error creating VRFv2Plus job" diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index ed81935fa2b..ab973ffe110 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -43,7 +43,7 @@ func CreateVRFV2PlusJob( return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrParseJob, err) } - job, err := chainlinkNode.MustCreateJob(&client.VRFV2PlusJobSpec{ + jobSpec := client.VRFV2PlusJobSpec{ Name: fmt.Sprintf("vrf-v2-plus-%s", jobUUID), CoordinatorAddress: vrfJobSpecConfig.CoordinatorAddress, FromAddresses: vrfJobSpecConfig.FromAddresses, @@ -56,7 +56,13 @@ func CreateVRFV2PlusJob( BatchFulfillmentGasMultiplier: vrfJobSpecConfig.BatchFulfillmentGasMultiplier, PollPeriod: vrfJobSpecConfig.PollPeriod, RequestTimeout: vrfJobSpecConfig.RequestTimeout, - }) + } + + if vrfJobSpecConfig.BatchFulfillmentEnabled { + jobSpec.BatchCoordinatorAddress = vrfJobSpecConfig.BatchCoordinatorAddress + } + + job, err := chainlinkNode.MustCreateJob(&jobSpec) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrCreatingVRFv2PlusJob, err) } @@ -201,6 +207,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, config *v vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ ForwardingAllowed: *config.VRFJobForwardingAllowed, CoordinatorAddress: contracts.CoordinatorV2Plus.Address(), + BatchCoordinatorAddress: contracts.BatchCoordinatorV2Plus.Address(), FromAddresses: vrfNode.TXKeyAddressStrings, EVMChainID: chainID.String(), MinIncomingConfirmations: int(*config.MinimumConfirmations), diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go index d19888fb706..3eb34d0491e 100644 --- a/integration-tests/client/chainlink_models.go +++ b/integration-tests/client/chainlink_models.go @@ -1160,7 +1160,8 @@ observationSource = """ type VRFV2PlusJobSpec struct { Name string `toml:"name"` CoordinatorAddress string `toml:"coordinatorAddress"` // Address of the VRF CoordinatorV2 contract - PublicKey string `toml:"publicKey"` // Public key of the proving key + BatchCoordinatorAddress string `toml:"batchCoordinatorAddress"` + PublicKey string `toml:"publicKey"` // Public key of the proving key ExternalJobID string `toml:"externalJobID"` ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node MinIncomingConfirmations int `toml:"minIncomingConfirmations"` @@ -1185,6 +1186,7 @@ type = "vrf" schemaVersion = 1 name = "{{.Name}}" coordinatorAddress = "{{.CoordinatorAddress}}" +{{ if .BatchFulfillmentEnabled }}batchCoordinatorAddress = "{{.BatchCoordinatorAddress}}"{{ else }}{{ end }} fromAddresses = [{{range .FromAddresses}}"{{.}}",{{end}}] evmChainID = "{{.EVMChainID}}" minIncomingConfirmations = {{.MinIncomingConfirmations}} @@ -1207,7 +1209,8 @@ observationSource = """ type VRFV2JobSpec struct { Name string `toml:"name"` CoordinatorAddress string `toml:"coordinatorAddress"` // Address of the VRF CoordinatorV2 contract - PublicKey string `toml:"publicKey"` // Public key of the proving key + BatchCoordinatorAddress string `toml:"batchCoordinatorAddress"` + PublicKey string `toml:"publicKey"` // Public key of the proving key ExternalJobID string `toml:"externalJobID"` ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node MinIncomingConfirmations int `toml:"minIncomingConfirmations"` @@ -1236,6 +1239,7 @@ schemaVersion = 1 name = "{{.Name}}" forwardingAllowed = {{.ForwardingAllowed}} coordinatorAddress = "{{.CoordinatorAddress}}" +{{ if .BatchFulfillmentEnabled }}batchCoordinatorAddress = "{{.BatchCoordinatorAddress}}"{{ else }}{{ end }} fromAddresses = [{{range .FromAddresses}}"{{.}}",{{end}}] evmChainID = "{{.EVMChainID}}" minIncomingConfirmations = {{.MinIncomingConfirmations}} diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index e2511c7292e..9e9c429d3ed 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -136,7 +136,9 @@ type ContractDeployer interface { DeployVRFV2PlusWrapperLoadTestConsumer(vrfV2PlusWrapperAddr string) (VRFv2PlusWrapperLoadTestConsumer, error) DeployVRFCoordinator(linkAddr string, bhsAddr string) (VRFCoordinator, error) DeployVRFCoordinatorV2(linkAddr string, bhsAddr string, linkEthFeedAddr string) (VRFCoordinatorV2, error) + DeployBatchVRFCoordinatorV2(coordinatorAddress string) (BatchVRFCoordinatorV2, error) DeployVRFCoordinatorV2_5(bhsAddr string) (VRFCoordinatorV2_5, error) + DeployBatchVRFCoordinatorV2Plus(coordinatorAddress string) (BatchVRFCoordinatorV2Plus, error) DeployVRFCoordinatorV2PlusUpgradedVersion(bhsAddr string) (VRFCoordinatorV2PlusUpgradedVersion, error) DeployVRFV2Wrapper(linkAddr string, linkEthFeedAddr string, coordinatorAddr string) (VRFV2Wrapper, error) DeployVRFV2PlusWrapper(linkAddr string, linkEthFeedAddr string, coordinatorAddr string, subId *big.Int) (VRFV2PlusWrapper, error) diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index f54d1a25936..97551a1b9ee 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -66,6 +66,7 @@ type VRFCoordinatorV2 interface { OwnerCancelSubscription(subID uint64) (*types.Transaction, error) ParseSubscriptionCanceled(log types.Log) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled, error) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) ParseLog(log types.Log) (generated.AbigenLog, error) CancelSubscription(subID uint64, to common.Address) (*types.Transaction, error) FindSubscriptionID(subID uint64) (uint64, error) @@ -122,6 +123,7 @@ type VRFCoordinatorV2_5 interface { WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForMigrationCompletedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, error) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) } @@ -160,6 +162,7 @@ type VRFCoordinatorV2PlusUpgradedVersion interface { WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForMigrationCompletedEvent(timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionMigrationCompleted, error) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) } @@ -365,6 +368,13 @@ type BatchBlockhashStore interface { Address() string } +type BatchVRFCoordinatorV2 interface { + Address() string +} +type BatchVRFCoordinatorV2Plus interface { + Address() string +} + type VRFMockETHLINKFeed interface { Address() string LatestRoundData() (*big.Int, error) diff --git a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go index 473b308dc42..18948ec38df 100644 --- a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go +++ b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go @@ -13,7 +13,6 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" @@ -114,24 +113,6 @@ func (e *EthereumContractDeployer) DeployVRFBeacon(vrfCoordinatorAddress string, }, err } -// DeployBatchBlockhashStore deploys DeployBatchBlockhashStore contract -func (e *EthereumContractDeployer) DeployBatchBlockhashStore(blockhashStoreAddr string) (BatchBlockhashStore, error) { - address, _, instance, err := e.client.DeployContract("BatchBlockhashStore", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return batch_blockhash_store.DeployBatchBlockhashStore(auth, backend, common.HexToAddress(blockhashStoreAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumBatchBlockhashStore{ - client: e.client, - batchBlockhashStore: instance.(*batch_blockhash_store.BatchBlockhashStore), - address: address, - }, err -} - // todo - solve import cycle func DecodeHexTo32ByteArray(val string) ([32]byte, error) { var byteArray [32]byte diff --git a/integration-tests/contracts/ethereum_vrf_common.go b/integration-tests/contracts/ethereum_vrf_common.go index d7eafe42a07..a57cfec8933 100644 --- a/integration-tests/contracts/ethereum_vrf_common.go +++ b/integration-tests/contracts/ethereum_vrf_common.go @@ -15,6 +15,7 @@ import ( type Coordinator interface { ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) Address() string WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) @@ -89,21 +90,33 @@ func parseRequestRandomnessLogs(coordinator Coordinator, logs []*types.Log) (*Co var err error for _, eventLog := range logs { for _, topic := range eventLog.Topics { - if topic.Cmp(vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested{}.Topic()) == 0 { + if topic.Cmp(vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested{}.Topic()) == 0 || + topic.Cmp(vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested{}.Topic()) == 0 { randomWordsRequestedEvent, err = coordinator.ParseRandomWordsRequested(*eventLog) if err != nil { return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) } } - if topic.Cmp(vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested{}.Topic()) == 0 { - randomWordsRequestedEvent, err = coordinator.ParseRandomWordsRequested(*eventLog) + } + } + return randomWordsRequestedEvent, nil +} + +func ParseRandomWordsFulfilledLogs(coordinator Coordinator, logs []*types.Log) ([]*CoordinatorRandomWordsFulfilled, error) { + var randomWordsFulfilledEventArr []*CoordinatorRandomWordsFulfilled + for _, eventLog := range logs { + for _, topic := range eventLog.Topics { + if topic.Cmp(vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled{}.Topic()) == 0 || + topic.Cmp(vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled{}.Topic()) == 0 { + randomWordsFulfilledEvent, err := coordinator.ParseRandomWordsFulfilled(*eventLog) if err != nil { - return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) + return nil, fmt.Errorf("parse RandomWordsFulfilled log failed, err: %w", err) } + randomWordsFulfilledEventArr = append(randomWordsFulfilledEventArr, randomWordsFulfilledEvent) } } } - return randomWordsRequestedEvent, nil + return randomWordsFulfilledEventArr, nil } func RetrieveRequestRandomnessLogs(coordinator Coordinator, client blockchain.EVMClient, tx *types.Transaction) (*CoordinatorRandomWordsRequested, error) { @@ -120,5 +133,4 @@ func RetrieveRequestRandomnessLogs(coordinator Coordinator, client blockchain.EV return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err) } return parseRequestRandomnessLogs(coordinator, receipt.Logs) - } diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index c2f12e29446..8484979164b 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -95,6 +95,24 @@ func (e *EthereumContractDeployer) DeployBlockhashStore() (BlockHashStore, error }, err } +// DeployBatchBlockhashStore deploys DeployBatchBlockhashStore contract +func (e *EthereumContractDeployer) DeployBatchBlockhashStore(blockhashStoreAddr string) (BatchBlockhashStore, error) { + address, _, instance, err := e.client.DeployContract("BatchBlockhashStore", func( + auth *bind.TransactOpts, + backend bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return batch_blockhash_store.DeployBatchBlockhashStore(auth, backend, common.HexToAddress(blockhashStoreAddr)) + }) + if err != nil { + return nil, err + } + return &LegacyEthereumBatchBlockhashStore{ + client: e.client, + batchBlockhashStore: instance.(*batch_blockhash_store.BatchBlockhashStore), + address: address, + }, err +} + // DeployVRFCoordinator deploys VRF coordinator contract func (e *EthereumContractDeployer) DeployVRFCoordinator(linkAddr string, bhsAddr string) (VRFCoordinator, error) { address, _, instance, err := e.client.DeployContract("VRFCoordinator", func( diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index c5116856d48..e617d8a0c03 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_mock_ethlink_aggregator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner" @@ -37,6 +38,12 @@ type EthereumVRFCoordinatorV2 struct { coordinator *vrf_coordinator_v2.VRFCoordinatorV2 } +type EthereumBatchVRFCoordinatorV2 struct { + address *common.Address + client blockchain.EVMClient + batchCoordinator *batch_vrf_coordinator_v2.BatchVRFCoordinatorV2 +} + type EthereumVRFOwner struct { address *common.Address client blockchain.EVMClient @@ -112,6 +119,23 @@ func (e *EthereumContractDeployer) DeployVRFCoordinatorV2(linkAddr string, bhsAd }, err } +func (e *EthereumContractDeployer) DeployBatchVRFCoordinatorV2(coordinatorAddress string) (BatchVRFCoordinatorV2, error) { + address, _, instance, err := e.client.DeployContract("BatchVRFCoordinatorV2", func( + auth *bind.TransactOpts, + backend bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return batch_vrf_coordinator_v2.DeployBatchVRFCoordinatorV2(auth, backend, common.HexToAddress(coordinatorAddress)) + }) + if err != nil { + return nil, err + } + return &EthereumBatchVRFCoordinatorV2{ + client: e.client, + batchCoordinator: instance.(*batch_vrf_coordinator_v2.BatchVRFCoordinatorV2), + address: address, + }, err +} + func (e *EthereumContractDeployer) DeployVRFOwner(coordinatorAddr string) (VRFOwner, error) { address, _, instance, err := e.client.DeployContract("VRFOwner", func( auth *bind.TransactOpts, @@ -475,6 +499,21 @@ func (v *EthereumVRFCoordinatorV2) ParseRandomWordsRequested(log types.Log) (*Co }, nil } +func (v *EthereumVRFCoordinatorV2) ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) { + fulfilled, err := v.coordinator.ParseRandomWordsFulfilled(log) + if err != nil { + return nil, fmt.Errorf("failed to parse RandomWordsFulfilled event: %w", err) + } + + return &CoordinatorRandomWordsFulfilled{ + RequestId: fulfilled.RequestId, + OutputSeed: fulfilled.OutputSeed, + Payment: fulfilled.Payment, + Success: fulfilled.Success, + Raw: fulfilled.Raw, + }, nil +} + func (v *EthereumVRFCoordinatorV2) ParseLog(log types.Log) (generated.AbigenLog, error) { return v.coordinator.ParseLog(log) } @@ -1229,3 +1268,7 @@ func (v *EthereumVRFMockETHLINKFeed) SetBlockTimestampDeduction(blockTimestampDe } return v.client.ProcessTransaction(tx) } + +func (v *EthereumBatchVRFCoordinatorV2) Address() string { + return v.address.Hex() +} diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 6d4bfcea647..3755b78f75b 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" @@ -27,6 +28,12 @@ type EthereumVRFCoordinatorV2_5 struct { coordinator vrf_coordinator_v2_5.VRFCoordinatorV25Interface } +type EthereumBatchVRFCoordinatorV2Plus struct { + address *common.Address + client blockchain.EVMClient + batchCoordinator *batch_vrf_coordinator_v2plus.BatchVRFCoordinatorV2Plus +} + type EthereumVRFCoordinatorV2PlusUpgradedVersion struct { address *common.Address client blockchain.EVMClient @@ -127,10 +134,31 @@ func (e *EthereumContractDeployer) DeployVRFCoordinatorV2_5(bhsAddr string) (VRF }, err } +func (e *EthereumContractDeployer) DeployBatchVRFCoordinatorV2Plus(coordinatorAddress string) (BatchVRFCoordinatorV2Plus, error) { + address, _, instance, err := e.client.DeployContract("BatchVRFCoordinatorV2Plus", func( + auth *bind.TransactOpts, + backend bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return batch_vrf_coordinator_v2plus.DeployBatchVRFCoordinatorV2Plus(auth, backend, common.HexToAddress(coordinatorAddress)) + }) + if err != nil { + return nil, err + } + return &EthereumBatchVRFCoordinatorV2Plus{ + client: e.client, + batchCoordinator: instance.(*batch_vrf_coordinator_v2plus.BatchVRFCoordinatorV2Plus), + address: address, + }, err +} + func (v *EthereumVRFCoordinatorV2_5) Address() string { return v.address.Hex() } +func (v *EthereumBatchVRFCoordinatorV2Plus) Address() string { + return v.address.Hex() +} + func (v *EthereumVRFCoordinatorV2_5) HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error) { opts := &bind.CallOpts{ From: common.HexToAddress(v.client.GetDefaultWallet().Address()), @@ -187,6 +215,23 @@ func (v *EthereumVRFCoordinatorV2_5) ParseRandomWordsRequested(log types.Log) (* return coordinatorRandomWordsRequested, nil } +func (v *EthereumVRFCoordinatorV2_5) ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) { + fulfilled, err := v.coordinator.ParseRandomWordsFulfilled(log) + if err != nil { + return nil, fmt.Errorf("failed to parse RandomWordsFulfilled event: %w", err) + } + return &CoordinatorRandomWordsFulfilled{ + RequestId: fulfilled.RequestId, + OutputSeed: fulfilled.OutputSeed, + Payment: fulfilled.Payment, + SubId: fulfilled.SubId.String(), + NativePayment: fulfilled.NativePayment, + OnlyPremium: fulfilled.OnlyPremium, + Success: fulfilled.Success, + Raw: fulfilled.Raw, + }, nil +} + func (v *EthereumVRFCoordinatorV2_5) GetSubscription(ctx context.Context, subID *big.Int) (Subscription, error) { opts := &bind.CallOpts{ From: common.HexToAddress(v.client.GetDefaultWallet().Address()), @@ -1023,6 +1068,23 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) ParseRandomWordsRequested( return coordinatorRandomWordsRequested, nil } +func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) ParseRandomWordsFulfilled(log types.Log) (*CoordinatorRandomWordsFulfilled, error) { + fulfilled, err := v.coordinator.ParseRandomWordsFulfilled(log) + if err != nil { + return nil, fmt.Errorf("failed to parse RandomWordsFulfilled event: %w", err) + } + return &CoordinatorRandomWordsFulfilled{ + RequestId: fulfilled.RequestId, + OutputSeed: fulfilled.OutputSeed, + Payment: fulfilled.Payment, + SubId: fulfilled.SubId.String(), + NativePayment: fulfilled.NativePayment, + OnlyPremium: fulfilled.OnlyPremium, + Success: fulfilled.Success, + Raw: fulfilled.Raw, + }, nil +} + func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) { eventsChannel := make(chan *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionConfigSet) subscription, err := v.coordinator.WatchConfigSet(nil, eventsChannel) diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 4dd23bce26f..ce9f448ee66 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -136,8 +136,7 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) - - t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + t.Run("VRF Node waits block confirmation number specified by the consumer before sending fulfilment on-chain", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) testConfig := configCopy.VRFv2.General @@ -184,7 +183,6 @@ func TestVRFv2Basic(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") }) - t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForJobRuns, err := vrfv2.SetupNewConsumersAndSubs( @@ -228,7 +226,6 @@ func TestVRFv2Basic(t *testing.T) { require.NoError(t, err, "error reading job runs") require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data)) }) - t.Run("Direct Funding (VRFV2Wrapper)", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) wrapperContracts, wrapperSubID, err := vrfv2.SetupVRFV2WrapperEnvironment( @@ -308,7 +305,6 @@ func TestVRFv2Basic(t *testing.T) { Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). Msg("Random Words Fulfilment Details For Link Billing") }) - t.Run("Oracle Withdraw", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForOracleWithDraw, err := vrfv2.SetupNewConsumersAndSubs( @@ -370,7 +366,6 @@ func TestVRFv2Basic(t *testing.T) { "LINK funds were not returned after oracle withdraw", ) }) - t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) _, subIDsForCancelling, err := vrfv2.SetupNewConsumersAndSubs( @@ -453,7 +448,6 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, 0, subBalanceLink.Cmp(subFundsReturnedLinkActual), "Returned LINK funds are not equal to sub balance that was cancelled") }) - t.Run("Owner Canceling Sub And Returning Funds While Having Pending Requests", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) // Underfund subscription to force fulfillments to fail @@ -1193,3 +1187,297 @@ func TestVRFV2NodeReorg(t *testing.T) { require.Error(t, err, "fulfillment should not be generated for the request which was made on reorged fork on Simulated Chain") }) } + +func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []uint64 + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2) + require.NoError(t, err, "Error getting config") + vrfv2Config := config.VRFv2 + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2Config.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2Config.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2 universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill + //callback gas limit set by consumer = 500k + // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill + + batchFulfilmentMaxGas := *config.VRFv2.General.MaxGasLimitCoordinatorConfig + 400_000 + config.VRFv2.General.CallbackGasLimit = ptr.Ptr(uint32(500_000)) + + expectedNumberOfFulfillmentsInsideOneBatchFulfillment := (batchFulfilmentMaxGas / *config.VRFv2.General.CallbackGasLimit) - 1 + randRequestCount := expectedNumberOfFulfillmentsInsideOneBatchFulfillment + + t.Run("Batch Fulfillment Enabled", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + + vrfNode, exists := nodeTypeToNodeMap[vrfcommon.VRF] + require.True(t, exists, "VRF Node does not exist") + + //ensure that no job present on the node + err = actions.DeleteJobs([]*client.ChainlinkClient{vrfNode.CLNode.API}) + require.NoError(t, err) + + batchFullfillmentEnabled := true + // create job with batch fulfillment enabled + vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ + ForwardingAllowed: *configCopy.VRFv2.General.VRFJobForwardingAllowed, + CoordinatorAddress: vrfContracts.CoordinatorV2.Address(), + BatchCoordinatorAddress: vrfContracts.BatchCoordinatorV2.Address(), + FromAddresses: vrfNode.TXKeyAddressStrings, + EVMChainID: fmt.Sprint(chainID), + MinIncomingConfirmations: int(*configCopy.VRFv2.General.MinimumConfirmations), + PublicKey: vrfKey.PubKeyCompressed, + EstimateGasMultiplier: *configCopy.VRFv2.General.VRFJobEstimateGasMultiplier, + BatchFulfillmentEnabled: batchFullfillmentEnabled, + BatchFulfillmentGasMultiplier: *configCopy.VRFv2.General.VRFJobBatchFulfillmentGasMultiplier, + PollPeriod: configCopy.VRFv2.General.VRFJobPollPeriod.Duration, + RequestTimeout: configCopy.VRFv2.General.VRFJobRequestTimeout.Duration, + SimulationBlock: configCopy.VRFv2.General.VRFJobSimulationBlock, + VRFOwnerConfig: &vrfcommon.VRFOwnerConfig{ + UseVRFOwner: false, + }, + } + + l.Info(). + Msg("Creating VRFV2 Job with `batchFulfillmentEnabled = true`") + job, err := vrfv2.CreateVRFV2Job( + vrfNode.CLNode.API, + vrfJobSpecConfig, + ) + require.NoError(t, err, "error creating job with higher timeout") + vrfNode.Job = job + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) + + // test and assert + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + var wgAllRequestsFulfilled sync.WaitGroup + wgAllRequestsFulfilled.Add(1) + requestCount, fulfilmentCount, err := vrfcommon.WaitForRequestCountEqualToFulfilmentCount(testcontext.Get(t), consumers[0], 2*time.Minute, &wgAllRequestsFulfilled) + require.NoError(t, err) + wgAllRequestsFulfilled.Wait() + + l.Info(). + Interface("Request Count", requestCount). + Interface("Fulfilment Count", fulfilmentCount). + Msg("Request/Fulfilment Stats") + + clNodeTxs, resp, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTransactions() + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + var batchFulfillmentTxs []client.TransactionData + for _, tx := range clNodeTxs.Data { + if common.HexToAddress(tx.Attributes.To).Cmp(common.HexToAddress(vrfContracts.BatchCoordinatorV2.Address())) == 0 { + batchFulfillmentTxs = append(batchFulfillmentTxs, tx) + } + } + // verify that all fulfillments should be inside one tx + require.Equal(t, 1, len(batchFulfillmentTxs)) + + fulfillmentTx, _, err := actions.GetTxByHash(testcontext.Get(t), evmClient, randomWordsFulfilledEvent.Raw.TxHash) + require.NoError(t, err, "error getting tx from hash") + + fulfillmentTXToAddress := fulfillmentTx.To().String() + l.Info(). + Str("Actual Fulfillment Tx To Address", fulfillmentTXToAddress). + Str("BatchCoordinatorV2 Address", vrfContracts.BatchCoordinatorV2.Address()). + Msg("Fulfillment Tx To Address should be the BatchCoordinatorV2 Address when batch fulfillment is enabled") + + // verify that VRF node sends fulfillments via BatchCoordinator contract + require.Equal(t, vrfContracts.BatchCoordinatorV2.Address(), fulfillmentTXToAddress, "Fulfillment Tx To Address should be the BatchCoordinatorV2 Address when batch fulfillment is enabled") + + fulfillmentTxReceipt, err := evmClient.GetTxReceipt(fulfillmentTx.Hash()) + require.NoError(t, err) + + randomWordsFulfilledLogs, err := contracts.ParseRandomWordsFulfilledLogs(vrfContracts.CoordinatorV2, fulfillmentTxReceipt.Logs) + require.NoError(t, err) + + // verify that all fulfillments should be inside one tx + require.Equal(t, int(randRequestCount), len(randomWordsFulfilledLogs)) + }) + t.Run("Batch Fulfillment Disabled", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + + vrfNode, exists := nodeTypeToNodeMap[vrfcommon.VRF] + require.True(t, exists, "VRF Node does not exist") + //ensure that no job present on the node + err = actions.DeleteJobs([]*client.ChainlinkClient{vrfNode.CLNode.API}) + require.NoError(t, err) + + batchFullfillmentEnabled := false + + //create job with batchFulfillmentEnabled = false + vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ + ForwardingAllowed: *configCopy.VRFv2.General.VRFJobForwardingAllowed, + CoordinatorAddress: vrfContracts.CoordinatorV2.Address(), + BatchCoordinatorAddress: vrfContracts.BatchCoordinatorV2.Address(), + FromAddresses: vrfNode.TXKeyAddressStrings, + EVMChainID: fmt.Sprint(chainID), + MinIncomingConfirmations: int(*configCopy.VRFv2.General.MinimumConfirmations), + PublicKey: vrfKey.PubKeyCompressed, + EstimateGasMultiplier: *configCopy.VRFv2.General.VRFJobEstimateGasMultiplier, + BatchFulfillmentEnabled: batchFullfillmentEnabled, + BatchFulfillmentGasMultiplier: *configCopy.VRFv2.General.VRFJobBatchFulfillmentGasMultiplier, + PollPeriod: configCopy.VRFv2.General.VRFJobPollPeriod.Duration, + RequestTimeout: configCopy.VRFv2.General.VRFJobRequestTimeout.Duration, + SimulationBlock: configCopy.VRFv2.General.VRFJobSimulationBlock, + VRFOwnerConfig: &vrfcommon.VRFOwnerConfig{ + UseVRFOwner: false, + }, + } + + l.Info(). + Msg("Creating VRFV2 Job with `batchFulfillmentEnabled = false`") + job, err := vrfv2.CreateVRFV2Job( + vrfNode.CLNode.API, + vrfJobSpecConfig, + ) + require.NoError(t, err, "error creating job with higher timeout") + vrfNode.Job = job + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) + + // test and assert + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + var wgAllRequestsFulfilled sync.WaitGroup + wgAllRequestsFulfilled.Add(1) + requestCount, fulfilmentCount, err := vrfcommon.WaitForRequestCountEqualToFulfilmentCount(testcontext.Get(t), consumers[0], 2*time.Minute, &wgAllRequestsFulfilled) + require.NoError(t, err) + wgAllRequestsFulfilled.Wait() + + l.Info(). + Interface("Request Count", requestCount). + Interface("Fulfilment Count", fulfilmentCount). + Msg("Request/Fulfilment Stats") + + fulfillmentTx, _, err := actions.GetTxByHash(testcontext.Get(t), evmClient, randomWordsFulfilledEvent.Raw.TxHash) + require.NoError(t, err, "error getting tx from hash") + + fulfillmentTXToAddress := fulfillmentTx.To().String() + l.Info(). + Str("Actual Fulfillment Tx To Address", fulfillmentTXToAddress). + Str("CoordinatorV2 Address", vrfContracts.CoordinatorV2.Address()). + Msg("Fulfillment Tx To Address should be the CoordinatorV2 Address when batch fulfillment is disabled") + + // verify that VRF node sends fulfillments via Coordinator contract + require.Equal(t, vrfContracts.CoordinatorV2.Address(), fulfillmentTXToAddress, "Fulfillment Tx To Address should be the CoordinatorV2 Address when batch fulfillment is disabled") + + clNodeTxs, resp, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTransactions() + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + + var singleFulfillmentTxs []client.TransactionData + for _, tx := range clNodeTxs.Data { + if common.HexToAddress(tx.Attributes.To).Cmp(common.HexToAddress(vrfContracts.CoordinatorV2.Address())) == 0 { + singleFulfillmentTxs = append(singleFulfillmentTxs, tx) + } + } + // verify that all fulfillments should be in separate txs + require.Equal(t, int(randRequestCount), len(singleFulfillmentTxs)) + }) + +} diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index ae190e060ee..0ef4e716733 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -193,8 +193,7 @@ func TestVRFv2Plus(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) - - t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + t.Run("VRF Node waits block confirmation number specified by the consumer before sending fulfilment on-chain", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) testConfig := configCopy.VRFv2Plus.General var isNativeBilling = true @@ -238,7 +237,6 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") }) - t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false @@ -823,7 +821,6 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - //todo - move TransactionByHash to EVMClient in CTF fulfillmentTx, _, err := actions.GetTxByHash(testcontext.Get(t), evmClient, randomWordsFulfilledEvent.Raw.TxHash) require.NoError(t, err, "error getting tx from hash") fulfillmentTxFromAddress, err := actions.GetTxFromAddress(fulfillmentTx) @@ -958,7 +955,7 @@ func TestVRFv2PlusMigration(t *testing.T) { MinIncomingConfirmations: int(*configCopy.VRFv2Plus.General.MinimumConfirmations), PublicKey: vrfKey.VRFKey.Data.ID, EstimateGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobEstimateGasMultiplier, - BatchFulfillmentEnabled: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentEnabled, + BatchFulfillmentEnabled: false, BatchFulfillmentGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentGasMultiplier, PollPeriod: configCopy.VRFv2Plus.General.VRFJobPollPeriod.Duration, RequestTimeout: configCopy.VRFv2Plus.General.VRFJobRequestTimeout.Duration, @@ -1142,7 +1139,7 @@ func TestVRFv2PlusMigration(t *testing.T) { MinIncomingConfirmations: int(*configCopy.VRFv2Plus.General.MinimumConfirmations), PublicKey: vrfKey.VRFKey.Data.ID, EstimateGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobEstimateGasMultiplier, - BatchFulfillmentEnabled: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentEnabled, + BatchFulfillmentEnabled: false, BatchFulfillmentGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentGasMultiplier, PollPeriod: configCopy.VRFv2Plus.General.VRFJobPollPeriod.Duration, RequestTimeout: configCopy.VRFv2Plus.General.VRFJobRequestTimeout.Duration, @@ -1788,7 +1785,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { MinIncomingConfirmations: int(*configCopy.VRFv2Plus.General.MinimumConfirmations), PublicKey: vrfKey.PubKeyCompressed, EstimateGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobEstimateGasMultiplier, - BatchFulfillmentEnabled: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentEnabled, + BatchFulfillmentEnabled: false, BatchFulfillmentGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentGasMultiplier, PollPeriod: configCopy.VRFv2Plus.General.VRFJobPollPeriod.Duration, RequestTimeout: configCopy.VRFv2Plus.General.VRFJobRequestTimeout.Duration, @@ -2083,3 +2080,287 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { }) } + +func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + require.NoError(t, err, "Error getting config") + vrfv2PlusConfig := config.VRFv2Plus + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2PlusConfig.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2Plus universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill + //callback gas limit set by consumer = 500k + // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill + + batchFulfilmentMaxGas := *config.VRFv2Plus.General.MaxGasLimitCoordinatorConfig + 400_000 + config.VRFv2Plus.General.CallbackGasLimit = ptr.Ptr(uint32(500_000)) + + expectedNumberOfFulfillmentsInsideOneBatchFulfillment := (batchFulfilmentMaxGas / *config.VRFv2Plus.General.CallbackGasLimit) - 1 + randRequestCount := expectedNumberOfFulfillmentsInsideOneBatchFulfillment + + t.Run("Batch Fulfillment Enabled", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + var isNativeBilling = true + + vrfNode, exists := nodeTypeToNodeMap[vrfcommon.VRF] + require.True(t, exists, "VRF Node does not exist") + + //ensure that no job present on the node + err = actions.DeleteJobs([]*client.ChainlinkClient{vrfNode.CLNode.API}) + require.NoError(t, err) + + batchFullfillmentEnabled := true + // create job with batch fulfillment enabled + vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ + ForwardingAllowed: *configCopy.VRFv2Plus.General.VRFJobForwardingAllowed, + CoordinatorAddress: vrfContracts.CoordinatorV2Plus.Address(), + BatchCoordinatorAddress: vrfContracts.BatchCoordinatorV2Plus.Address(), + FromAddresses: vrfNode.TXKeyAddressStrings, + EVMChainID: fmt.Sprint(chainID), + MinIncomingConfirmations: int(*configCopy.VRFv2Plus.General.MinimumConfirmations), + PublicKey: vrfKey.PubKeyCompressed, + EstimateGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobEstimateGasMultiplier, + BatchFulfillmentEnabled: batchFullfillmentEnabled, + BatchFulfillmentGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentGasMultiplier, + PollPeriod: configCopy.VRFv2Plus.General.VRFJobPollPeriod.Duration, + RequestTimeout: configCopy.VRFv2Plus.General.VRFJobRequestTimeout.Duration, + SimulationBlock: configCopy.VRFv2Plus.General.VRFJobSimulationBlock, + VRFOwnerConfig: nil, + } + + l.Info(). + Msg("Creating VRFV2 Plus Job with `batchFulfillmentEnabled = true`") + job, err := vrfv2plus.CreateVRFV2PlusJob( + vrfNode.CLNode.API, + vrfJobSpecConfig, + ) + require.NoError(t, err, "error creating job with higher timeout") + vrfNode.Job = job + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) + + // test and assert + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + var wgAllRequestsFulfilled sync.WaitGroup + wgAllRequestsFulfilled.Add(1) + requestCount, fulfilmentCount, err := vrfcommon.WaitForRequestCountEqualToFulfilmentCount(testcontext.Get(t), consumers[0], 2*time.Minute, &wgAllRequestsFulfilled) + require.NoError(t, err) + wgAllRequestsFulfilled.Wait() + + l.Info(). + Interface("Request Count", requestCount). + Interface("Fulfilment Count", fulfilmentCount). + Msg("Request/Fulfilment Stats") + + clNodeTxs, resp, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTransactions() + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + var batchFulfillmentTxs []client.TransactionData + for _, tx := range clNodeTxs.Data { + if common.HexToAddress(tx.Attributes.To).Cmp(common.HexToAddress(vrfContracts.BatchCoordinatorV2Plus.Address())) == 0 { + batchFulfillmentTxs = append(batchFulfillmentTxs, tx) + } + } + // verify that all fulfillments should be inside one tx + require.Equal(t, 1, len(batchFulfillmentTxs)) + + fulfillmentTx, _, err := actions.GetTxByHash(testcontext.Get(t), evmClient, randomWordsFulfilledEvent.Raw.TxHash) + require.NoError(t, err, "error getting tx from hash") + + fulfillmentTXToAddress := fulfillmentTx.To().String() + l.Info(). + Str("Actual Fulfillment Tx To Address", fulfillmentTXToAddress). + Str("BatchCoordinatorV2Plus Address", vrfContracts.BatchCoordinatorV2Plus.Address()). + Msg("Fulfillment Tx To Address should be the BatchCoordinatorV2Plus Address when batch fulfillment is enabled") + + // verify that VRF node sends fulfillments via BatchCoordinator contract + require.Equal(t, vrfContracts.BatchCoordinatorV2Plus.Address(), fulfillmentTXToAddress, "Fulfillment Tx To Address should be the BatchCoordinatorV2Plus Address when batch fulfillment is enabled") + + fulfillmentTxReceipt, err := evmClient.GetTxReceipt(fulfillmentTx.Hash()) + require.NoError(t, err) + + randomWordsFulfilledLogs, err := contracts.ParseRandomWordsFulfilledLogs(vrfContracts.CoordinatorV2Plus, fulfillmentTxReceipt.Logs) + require.NoError(t, err) + + // verify that all fulfillments should be inside one tx + require.Equal(t, int(randRequestCount), len(randomWordsFulfilledLogs)) + }) + t.Run("Batch Fulfillment Disabled", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + var isNativeBilling = true + + vrfNode, exists := nodeTypeToNodeMap[vrfcommon.VRF] + require.True(t, exists, "VRF Node does not exist") + //ensure that no job present on the node + err = actions.DeleteJobs([]*client.ChainlinkClient{vrfNode.CLNode.API}) + require.NoError(t, err) + + batchFullfillmentEnabled := false + + //create job with batchFulfillmentEnabled = false + vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ + ForwardingAllowed: *configCopy.VRFv2Plus.General.VRFJobForwardingAllowed, + CoordinatorAddress: vrfContracts.CoordinatorV2Plus.Address(), + BatchCoordinatorAddress: vrfContracts.BatchCoordinatorV2Plus.Address(), + FromAddresses: vrfNode.TXKeyAddressStrings, + EVMChainID: fmt.Sprint(chainID), + MinIncomingConfirmations: int(*configCopy.VRFv2Plus.General.MinimumConfirmations), + PublicKey: vrfKey.PubKeyCompressed, + EstimateGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobEstimateGasMultiplier, + BatchFulfillmentEnabled: batchFullfillmentEnabled, + BatchFulfillmentGasMultiplier: *configCopy.VRFv2Plus.General.VRFJobBatchFulfillmentGasMultiplier, + PollPeriod: configCopy.VRFv2Plus.General.VRFJobPollPeriod.Duration, + RequestTimeout: configCopy.VRFv2Plus.General.VRFJobRequestTimeout.Duration, + SimulationBlock: configCopy.VRFv2Plus.General.VRFJobSimulationBlock, + VRFOwnerConfig: nil, + } + + l.Info(). + Msg("Creating VRFV2 Plus Job with `batchFulfillmentEnabled = false`") + job, err := vrfv2plus.CreateVRFV2PlusJob( + vrfNode.CLNode.API, + vrfJobSpecConfig, + ) + require.NoError(t, err, "error creating job with higher timeout") + vrfNode.Job = job + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) + + // test and assert + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + var wgAllRequestsFulfilled sync.WaitGroup + wgAllRequestsFulfilled.Add(1) + requestCount, fulfilmentCount, err := vrfcommon.WaitForRequestCountEqualToFulfilmentCount(testcontext.Get(t), consumers[0], 2*time.Minute, &wgAllRequestsFulfilled) + require.NoError(t, err) + wgAllRequestsFulfilled.Wait() + + l.Info(). + Interface("Request Count", requestCount). + Interface("Fulfilment Count", fulfilmentCount). + Msg("Request/Fulfilment Stats") + + fulfillmentTx, _, err := actions.GetTxByHash(testcontext.Get(t), evmClient, randomWordsFulfilledEvent.Raw.TxHash) + require.NoError(t, err, "error getting tx from hash") + + fulfillmentTXToAddress := fulfillmentTx.To().String() + l.Info(). + Str("Actual Fulfillment Tx To Address", fulfillmentTXToAddress). + Str("CoordinatorV2Plus Address", vrfContracts.CoordinatorV2Plus.Address()). + Msg("Fulfillment Tx To Address should be the CoordinatorV2Plus Address when batch fulfillment is disabled") + + // verify that VRF node sends fulfillments via Coordinator contract + require.Equal(t, vrfContracts.CoordinatorV2Plus.Address(), fulfillmentTXToAddress, "Fulfillment Tx To Address should be the CoordinatorV2Plus Address when batch fulfillment is disabled") + + clNodeTxs, resp, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTransactions() + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + + var singleFulfillmentTxs []client.TransactionData + for _, tx := range clNodeTxs.Data { + if common.HexToAddress(tx.Attributes.To).Cmp(common.HexToAddress(vrfContracts.CoordinatorV2Plus.Address())) == 0 { + singleFulfillmentTxs = append(singleFulfillmentTxs, tx) + } + } + // verify that all fulfillments should be in separate txs + require.Equal(t, int(randRequestCount), len(singleFulfillmentTxs)) + }) + +} diff --git a/integration-tests/testconfig/vrfv2/vrfv2.toml b/integration-tests/testconfig/vrfv2/vrfv2.toml index 012352f49b8..59affd85f5a 100644 --- a/integration-tests/testconfig/vrfv2/vrfv2.toml +++ b/integration-tests/testconfig/vrfv2/vrfv2.toml @@ -44,7 +44,7 @@ wrapper_consumer_funding_amount_link = 10 # VRF Job config vrf_job_forwarding_allowed = false vrf_job_estimate_gas_multiplier = 1.0 -vrf_job_batch_fulfillment_enabled = false +vrf_job_batch_fulfillment_enabled = true vrf_job_batch_fulfillment_gas_multiplier = 1.15 vrf_job_poll_period = "1s" vrf_job_request_timeout = "24h" diff --git a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml index 902ca3a2966..b420a1c1d88 100644 --- a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml +++ b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml @@ -48,7 +48,7 @@ coordinator_link_premium_percentage=20 # VRF Job config vrf_job_forwarding_allowed = false vrf_job_estimate_gas_multiplier = 1.1 -vrf_job_batch_fulfillment_enabled = false +vrf_job_batch_fulfillment_enabled = true vrf_job_batch_fulfillment_gas_multiplier = 1.15 vrf_job_poll_period = "1s" vrf_job_request_timeout = "24h" From 9141b527a9a3933dde896969f97bd2646837ddee Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Tue, 7 May 2024 13:19:31 -0400 Subject: [PATCH 29/35] Match postgres asdf version with CI (#13124) --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index 9db7d9b080d..9f41c03b1f7 100644 --- a/.tool-versions +++ b/.tool-versions @@ -2,7 +2,7 @@ golang 1.21.7 mockery 2.42.2 nodejs 16.16.0 pnpm 8.11.0 -postgres 13.3 +postgres 14.11 helm 3.10.3 zig 0.11.0 golangci-lint 1.55.2 From ed1f945d817fdeeda4b7c04b970944b9c3fa7242 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Tue, 7 May 2024 13:21:11 -0400 Subject: [PATCH 30/35] Update CI postgres setup (#13123) * Remove deprecated version field * Add pg_dump wrapper for db tests --- .github/actions/setup-postgres/bin/pg_dump | 23 +++++++++++++++++++ .../actions/setup-postgres/docker-compose.yml | 1 - 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100755 .github/actions/setup-postgres/bin/pg_dump diff --git a/.github/actions/setup-postgres/bin/pg_dump b/.github/actions/setup-postgres/bin/pg_dump new file mode 100755 index 00000000000..d8135ad824c --- /dev/null +++ b/.github/actions/setup-postgres/bin/pg_dump @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# +# This script acts as a docker replacement around pg_dump so that developers can +# run DB involved tests locally without having postgres installed. +# +# Installation: +# - Make sure that your PATH doesn't already contain a postgres installation +# - Add this script to your PATH +# +# Usage: +# You should be able to setup your test db via: +# - go build -o chainlink.test . # Build the chainlink binary to run test db prep commands from +# - export CL_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable" +# - pushd .github/actions/setup-postgres/ # Navigate to the setup-postgres action so we can spin up a docker postgres +# instance +# - docker compose up # Spin up postgres +# - ./chainlink.test local db preparetest # Run the db migration, which will shell out to our pg_dump wrapper too. +# - popd +# - go test -timeout 30s ./core/services/workflows/... -v # Run tests that use the database + +cd "$(dirname "$0")" || exit + +docker compose exec -T postgres pg_dump "$@" diff --git a/.github/actions/setup-postgres/docker-compose.yml b/.github/actions/setup-postgres/docker-compose.yml index 3acaa1ecd1b..23f8d82b917 100644 --- a/.github/actions/setup-postgres/docker-compose.yml +++ b/.github/actions/setup-postgres/docker-compose.yml @@ -1,5 +1,4 @@ name: gha_postgres -version: "3.8" services: postgres: ports: From 153cce23cb53fa92d4e6997da4d3241cc3dd7c23 Mon Sep 17 00:00:00 2001 From: ilija42 <57732589+ilija42@users.noreply.github.com> Date: Tue, 7 May 2024 19:50:28 +0200 Subject: [PATCH 31/35] Bump common and Implement dummy chain reader common changes (#13122) * Update chainlink-common * Add temporary dummy implementation for ChainReader changes from common * Update TestChainReader to match chainlink-common chain reader changes --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/relay/evm/chain_reader.go | 5 +++++ core/services/relay/evm/chain_reader_test.go | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 10 files changed, 19 insertions(+), 14 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 3963538b2c3..d025a83d92b 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index daedbe64eb3..612a99b286f 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,8 +1185,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.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 h1:6PP8T5py2K+0Vd+8LP0DlDvPKhyXXhz1i2RwKoFhKPI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index df46e7636d2..f40da18fe27 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -37,6 +38,10 @@ type chainReader struct { commonservices.StateMachine } +func (cr *chainReader) QueryKey(_ context.Context, _ string, _ query.KeyFilter, _ query.LimitAndSort, _ any) ([]commontypes.Sequence, error) { + return nil, nil +} + // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, client evmclient.Client, config types.ChainReaderConfig) (ChainReaderService, error) { diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index 3a0d45b67c5..f9985f2ed7f 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -49,8 +49,8 @@ const ( func TestChainReader(t *testing.T) { t.Parallel() it := &chainReaderInterfaceTester{} - RunChainReaderInterfaceTests(t, it) - RunChainReaderInterfaceTests(t, commontestutils.WrapChainReaderTesterForLoop(it)) + RunChainReaderGetLatestValueInterfaceTests(t, it) + RunChainReaderGetLatestValueInterfaceTests(t, commontestutils.WrapChainReaderTesterForLoop(it)) t.Run("Dynamically typed topics can be used to filter and have type correct in return", func(t *testing.T) { it.Setup(t) diff --git a/go.mod b/go.mod index 3e691e95405..f6156741089 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab diff --git a/go.sum b/go.sum index 90faeacb057..ca404242d88 100644 --- a/go.sum +++ b/go.sum @@ -1180,8 +1180,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.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 h1:6PP8T5py2K+0Vd+8LP0DlDvPKhyXXhz1i2RwKoFhKPI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index d8210ccc123..5fbb659b25d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -26,7 +26,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 95f686a6d28..d34b605c89f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1517,8 +1517,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.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 h1:6PP8T5py2K+0Vd+8LP0DlDvPKhyXXhz1i2RwKoFhKPI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c179a3619f7..36e32d9974a 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 2c31f0fa335..a7c0fa60ad6 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1500,8 +1500,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.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 h1:6PP8T5py2K+0Vd+8LP0DlDvPKhyXXhz1i2RwKoFhKPI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From a0d1ce5e9cddc540bba8eb193865646cf0ebc0a8 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Tue, 7 May 2024 16:55:36 -0700 Subject: [PATCH 32/35] refactor changesets release preview workflow (#13094) * add format_changelog script * refactor changesets release preview workflow * update branch to test and add changeset file * fix * add git-token * add set_pr_body and refactor workflow * fix multi-line string output * fix * fix format * remove testing branch trigger * refactor * add explicit fail exit * refactor * add back set -euo pipefail --- .changeset/many-comics-begin.md | 5 + .github/workflows/changesets-preview-pr.yml | 67 ++++++++ .github/workflows/cicd-changesets.yml | 74 --------- tools/ci/format_changelog | 163 ++++++++++++++++++++ 4 files changed, 235 insertions(+), 74 deletions(-) create mode 100644 .changeset/many-comics-begin.md create mode 100644 .github/workflows/changesets-preview-pr.yml delete mode 100644 .github/workflows/cicd-changesets.yml create mode 100755 tools/ci/format_changelog diff --git a/.changeset/many-comics-begin.md b/.changeset/many-comics-begin.md new file mode 100644 index 00000000000..139023916df --- /dev/null +++ b/.changeset/many-comics-begin.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Refactor changesets release preview workflow #internal diff --git a/.github/workflows/changesets-preview-pr.yml b/.github/workflows/changesets-preview-pr.yml new file mode 100644 index 00000000000..03d1fecf618 --- /dev/null +++ b/.github/workflows/changesets-preview-pr.yml @@ -0,0 +1,67 @@ +# +# This action creates or updates a Release Preview PR that shows which changes are going to be part of the next release. +# + +name: Release Preview - Changeset + +on: + push: + branches: + - develop + +jobs: + changesets-release-preview: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: change + with: + token: ${{ secrets.GITHUB_TOKEN }} + filters: | + core-changeset: + - '.changeset/**' + + - name: Setup pnpm + uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 + if: steps.change.outputs.core-changeset == 'true' + with: + version: ^8.0.0 + + - name: Setup node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + if: steps.change.outputs.core-changeset == 'true' + with: + node-version: 20 + cache: pnpm + cache-dependency-path: ./pnpm-lock.yaml + + - name: Generate new changelog + if: steps.change.outputs.core-changeset == 'true' + id: changelog + run: pnpm install && ./tools/ci/format_changelog + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create release preview PR + if: steps.change.outputs.core-changeset == 'true' + uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + with: + git-token: ${{ secrets.GITHUB_TOKEN }} + add-paths: | + .changeset/** + CHANGELOG.md + commit-message: "changeset: release preview" + committer: app-token-issuer-releng[bot] + branch: changesets/release-preview + title: "[DO NOT MERGE] Changeset Release Preview - v${{ steps.changelog.outputs.version }}" + body: ${{ steps.changelog.outputs.pr_body }} + draft: true + labels: | + release-preview + do-not-merge diff --git a/.github/workflows/cicd-changesets.yml b/.github/workflows/cicd-changesets.yml deleted file mode 100644 index 96363588319..00000000000 --- a/.github/workflows/cicd-changesets.yml +++ /dev/null @@ -1,74 +0,0 @@ -# -# This action creates or updates a Release Preview PR that shows which changes are going to be part of the next release -# when a PR is merged into develop branch -# - -name: Release Preview - Changeset - -on: - push: - branches: - - develop - -jobs: - cicd-changesets: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - actions: read - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changeset-added - with: - token: ${{ secrets.GITHUB_TOKEN }} - filters: | - core-changeset: - - added: '.changeset/**' - - - name: Setup pnpm - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 - if: steps.changeset-added.outputs.core-changeset == 'true' - with: - version: ^8.0.0 - - - name: Setup node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 - if: steps.changeset-added.outputs.core-changeset == 'true' - with: - node-version: 20 - cache: pnpm - cache-dependency-path: ./pnpm-lock.yaml - - - name: Run changeset version - run: pnpm install && pnpm changeset version - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: steps.changeset-added.outputs.core-changeset == 'true' - - - name: Get release version - if: steps.changeset-added.outputs.core-changeset == 'true' - id: get-release-version - run: echo "version=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT - - - name: cicd-changesets - if: steps.changeset-added.outputs.core-changeset == 'true' - uses: smartcontractkit/.github/actions/cicd-changesets@6da79c7b9f14bec077df2c1ad40d53823b409d9c # cicd-changesets@0.3.3 - with: - # general inputs - git-user: app-token-issuer-releng[bot] - git-email: app-token-issuer-releng[bot]@users.noreply.github.com - pnpm-use-cache: false - pr-draft: true - pr-title: "[DO NOT MERGE] Changeset Release Preview - v${{ steps.get-release-version.outputs.version }}" - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }} - aws-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} - # grafana inputs - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/tools/ci/format_changelog b/tools/ci/format_changelog new file mode 100755 index 00000000000..7e508a1e129 --- /dev/null +++ b/tools/ci/format_changelog @@ -0,0 +1,163 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [[ -z "${GITHUB_OUTPUT:-}" ]]; then + echo "GITHUB_OUTPUT environment variable is not set." + exit 1 +fi + +create_changesets_json() { + echo "[[]]" > changesets.json +} + +create_tags_json() { + json="{}" + for tag in "${tags_list[@]}"; do + tag=${tag:1} + json=$(jq --arg k "$tag" '.[$k] = []' <<< "$json") + done + echo "$json" > tags.json +} + +append_changeset_content() { + if [[ $1 != "" ]]; then + jq --argjson idx "$changesets_index" --arg str "$1" \ + '.[$idx] += [$str]' changesets.json > tmp.json && mv tmp.json changesets.json + fi +} + +append_changelog_content() { + for tag in "${tags_list[@]}"; do + tag=${tag:1} + array_length=$(jq -r --arg key "$tag" '.[$key] | length' tags.json) + if [[ $array_length -eq 0 ]]; then + continue + fi + changesets=$(jq -r --arg key "$tag" '.[$key] | join("\n\n")' tags.json) + read -d '' changelog_content <> $GITHUB_OUTPUT + echo "${pr_body}" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT +} + +set_new_changelog_content() { + read -d '' new_changelog < CHANGELOG.md +} + +# checks for tags in each changeset entry and append to tags.json +match_tags() { + changesets_with_index=$(jq -r 'to_entries | .[] | "\(.key) \(.value | join(" "))"' changesets.json) + + echo "$changesets_with_index" | while IFS= read -r line; do + index="${line%% *}" + changeset_content="${line#* }" + changeset_formatted=$(jq -r --argjson idx "$index" '.[$idx] | join("\n")' changesets.json) + found_tag="" + for tag in "${tags_list[@]}"; do + if [[ "$changeset_content" =~ $tag ]]; then + found_tag=${tag:1} + jq --arg key "$found_tag" --arg val "$changeset_formatted" \ + '.[$key] += [$val]' tags.json > tmp.json && mv tmp.json tags.json + fi + done + if [[ $found_tag == "" ]] && [[ ! -z $changeset_content ]]; then + found_tag="untagged" + jq --arg key "$found_tag" --arg val "$changeset_formatted" \ + '.[$key] += [$val]' tags.json > tmp.json && mv tmp.json tags.json + fi + done +} + +cleanup() { + rm -f CHANGELOG.md.tmp + rm -f changesets.json + rm -f tags.json +} + +### SCRIPT STARTS HERE ### + +tail -n +2 CHANGELOG.md > CHANGELOG.md.tmp + +pnpm changeset version + +version=$(jq -r '.version' package.json) +echo "version=$version" >> $GITHUB_OUTPUT + +read -d '' changelog_content < Date: Wed, 8 May 2024 09:47:00 -0400 Subject: [PATCH 33/35] CCIP price cache use DB timestamp (#13133) * use statement timestamp * expiration uses db timestamp * changeset --- .changeset/poor-gorillas-give.md | 5 +++++ core/services/ccip/mocks/orm.go | 22 ++++++++++------------ core/services/ccip/orm.go | 26 ++++++++++++-------------- core/services/ccip/orm_test.go | 22 ++++++++++++---------- 4 files changed, 39 insertions(+), 36 deletions(-) create mode 100644 .changeset/poor-gorillas-give.md diff --git a/.changeset/poor-gorillas-give.md b/.changeset/poor-gorillas-give.md new file mode 100644 index 00000000000..67128f654bf --- /dev/null +++ b/.changeset/poor-gorillas-give.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#changed CCIP price cache to use DB timestamp diff --git a/core/services/ccip/mocks/orm.go b/core/services/ccip/mocks/orm.go index b9afc6c8695..ea6b07dc637 100644 --- a/core/services/ccip/mocks/orm.go +++ b/core/services/ccip/mocks/orm.go @@ -8,8 +8,6 @@ import ( ccip "github.com/smartcontractkit/chainlink/v2/core/services/ccip" mock "github.com/stretchr/testify/mock" - - time "time" ) // ORM is an autogenerated mock type for the ORM type @@ -17,17 +15,17 @@ type ORM struct { mock.Mock } -// ClearGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, to -func (_m *ORM) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { - ret := _m.Called(ctx, destChainSelector, to) +// ClearGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, expireSec +func (_m *ORM) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { + ret := _m.Called(ctx, destChainSelector, expireSec) if len(ret) == 0 { panic("no return value specified for ClearGasPricesByDestChain") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, time.Time) error); ok { - r0 = rf(ctx, destChainSelector, to) + if rf, ok := ret.Get(0).(func(context.Context, uint64, int) error); ok { + r0 = rf(ctx, destChainSelector, expireSec) } else { r0 = ret.Error(0) } @@ -35,17 +33,17 @@ func (_m *ORM) ClearGasPricesByDestChain(ctx context.Context, destChainSelector return r0 } -// ClearTokenPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, to -func (_m *ORM) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { - ret := _m.Called(ctx, destChainSelector, to) +// ClearTokenPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, expireSec +func (_m *ORM) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { + ret := _m.Called(ctx, destChainSelector, expireSec) if len(ret) == 0 { panic("no return value specified for ClearTokenPricesByDestChain") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, time.Time) error); ok { - r0 = rf(ctx, destChainSelector, to) + if rf, ok := ret.Get(0).(func(context.Context, uint64, int) error); ok { + r0 = rf(ctx, destChainSelector, expireSec) } else { r0 = ret.Error(0) } diff --git a/core/services/ccip/orm.go b/core/services/ccip/orm.go index 8af7762b18d..6c21520d435 100644 --- a/core/services/ccip/orm.go +++ b/core/services/ccip/orm.go @@ -40,8 +40,8 @@ type ORM interface { InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []GasPriceUpdate) error InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []TokenPriceUpdate) error - ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error - ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error + ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error + ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error } type orm struct { @@ -99,7 +99,6 @@ func (o *orm) InsertGasPricesForDestChain(ctx context.Context, destChainSelector return nil } - now := time.Now() insertData := make([]map[string]interface{}, 0, len(gasPrices)) for _, price := range gasPrices { insertData = append(insertData, map[string]interface{}{ @@ -107,12 +106,12 @@ func (o *orm) InsertGasPricesForDestChain(ctx context.Context, destChainSelector "job_id": jobId, "source_chain_selector": price.SourceChainSelector, "gas_price": price.GasPrice, - "created_at": now, }) } + // using statement_timestamp() to make testing easier stmt := `INSERT INTO ccip.observed_gas_prices (chain_selector, job_id, source_chain_selector, gas_price, created_at) - VALUES (:chain_selector, :job_id, :source_chain_selector, :gas_price, :created_at);` + VALUES (:chain_selector, :job_id, :source_chain_selector, :gas_price, statement_timestamp());` _, err := o.ds.NamedExecContext(ctx, stmt, insertData) if err != nil { err = fmt.Errorf("error inserting gas prices for job %d: %w", jobId, err) @@ -126,7 +125,6 @@ func (o *orm) InsertTokenPricesForDestChain(ctx context.Context, destChainSelect return nil } - now := time.Now() insertData := make([]map[string]interface{}, 0, len(tokenPrices)) for _, price := range tokenPrices { insertData = append(insertData, map[string]interface{}{ @@ -134,12 +132,12 @@ func (o *orm) InsertTokenPricesForDestChain(ctx context.Context, destChainSelect "job_id": jobId, "token_addr": price.TokenAddr, "token_price": price.TokenPrice, - "created_at": now, }) } + // using statement_timestamp() to make testing easier stmt := `INSERT INTO ccip.observed_token_prices (chain_selector, job_id, token_addr, token_price, created_at) - VALUES (:chain_selector, :job_id, :token_addr, :token_price, :created_at);` + VALUES (:chain_selector, :job_id, :token_addr, :token_price, statement_timestamp());` _, err := o.ds.NamedExecContext(ctx, stmt, insertData) if err != nil { err = fmt.Errorf("error inserting token prices for job %d: %w", jobId, err) @@ -148,16 +146,16 @@ func (o *orm) InsertTokenPricesForDestChain(ctx context.Context, destChainSelect return err } -func (o *orm) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { - stmt := `DELETE FROM ccip.observed_gas_prices WHERE chain_selector = $1 AND created_at < $2` +func (o *orm) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { + stmt := `DELETE FROM ccip.observed_gas_prices WHERE chain_selector = $1 AND created_at < (statement_timestamp() - $2 * interval '1 second')` - _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, to) + _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, expireSec) return err } -func (o *orm) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, to time.Time) error { - stmt := `DELETE FROM ccip.observed_token_prices WHERE chain_selector = $1 AND created_at < $2` +func (o *orm) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { + stmt := `DELETE FROM ccip.observed_token_prices WHERE chain_selector = $1 AND created_at < (statement_timestamp() - $2 * interval '1 second')` - _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, to) + _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, expireSec) return err } diff --git a/core/services/ccip/orm_test.go b/core/services/ccip/orm_test.go index 741cf4b5b38..7b7b8d82710 100644 --- a/core/services/ccip/orm_test.go +++ b/core/services/ccip/orm_test.go @@ -212,7 +212,8 @@ func TestORM_InsertAndDeleteGasPrices(t *testing.T) { assert.NoError(t, err) } - interimTimeStamp := time.Now() + sleepSec := 2 + time.Sleep(time.Duration(sleepSec) * time.Second) // insert for the 2nd time after interimTimeStamp for _, updatesPerSelector := range updates { @@ -222,13 +223,13 @@ func TestORM_InsertAndDeleteGasPrices(t *testing.T) { assert.Equal(t, 2*numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) - // clear by interimTimeStamp should delete rows inserted before it - err := orm.ClearGasPricesByDestChain(ctx, destSelector, interimTimeStamp) + // clear by sleepSec should delete rows inserted before it + err := orm.ClearGasPricesByDestChain(ctx, destSelector, sleepSec) assert.NoError(t, err) assert.Equal(t, numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) - // clear by Now() should delete all rows - err = orm.ClearGasPricesByDestChain(ctx, destSelector, time.Now()) + // clear by 0 expiration seconds should delete all rows + err = orm.ClearGasPricesByDestChain(ctx, destSelector, 0) assert.NoError(t, err) assert.Equal(t, 0, getGasTableRowCount(t, db)) } @@ -324,7 +325,8 @@ func TestORM_InsertAndDeleteTokenPrices(t *testing.T) { assert.NoError(t, err) } - interimTimeStamp := time.Now() + sleepSec := 2 + time.Sleep(time.Duration(sleepSec) * time.Second) // insert for the 2nd time after interimTimeStamp for _, updatesPerAddr := range updates { @@ -334,13 +336,13 @@ func TestORM_InsertAndDeleteTokenPrices(t *testing.T) { assert.Equal(t, 2*numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) - // clear by interimTimeStamp should delete rows inserted before it - err := orm.ClearTokenPricesByDestChain(ctx, destSelector, interimTimeStamp) + // clear by sleepSec should delete rows inserted before it + err := orm.ClearTokenPricesByDestChain(ctx, destSelector, sleepSec) assert.NoError(t, err) assert.Equal(t, numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) - // clear by Now() should delete all rows - err = orm.ClearTokenPricesByDestChain(ctx, destSelector, time.Now()) + // clear by 0 expiration seconds should delete all rows + err = orm.ClearTokenPricesByDestChain(ctx, destSelector, 0) assert.NoError(t, err) assert.Equal(t, 0, getTokenTableRowCount(t, db)) } From dc941789f45fbafaae14b5720e63c1483e9fc862 Mon Sep 17 00:00:00 2001 From: ilija42 <57732589+ilija42@users.noreply.github.com> Date: Wed, 8 May 2024 16:33:57 +0200 Subject: [PATCH 34/35] [BCF-3048] - Chain reader event querying (#12486) * Simple DSL PoC * Simple DSL PoC * Removing NamedFilter from the API * Resolve merge issues * Use dsl filters from common, add some overrides and TODO placeholders * Add chain agnostic keys Querying mappings and implement some parts * Fix merge errors * Improve chain agnostic filter remapping * Move log confirmations to evm types * Remove unused KeysMappings from ChainContractReader * Rough implementation of how chain reader should handle query keys * Fix log poller mock gen and set chainlink-feeds to altest * Update chain reader to properly parse new proto * Add method to chain reader for retrieving data type by key * Add log to sequences parsing for QueryKey and QueryKeyByValues * Change multiple keys querying to make sense and cleanup * Further chain reader keys querying cleanup * Add chain agnostic head to sequences * Match chainlink-common changes * Add empty implementations of new QueryKey methodsfrom chainlink-common * Match new Query keys by equality definition from common in chain reader * Merge QueryByKey/ValuesIn/ValueEquality into QueryByKeyValuesComparison * Flatten bindings into just readBindings and use it for keys querying * Add data word querying by key support * Match chainlink-common chain reader changes * Extract addr context from read bindings and match common changes * Remove code that is out of scope for PR * Cleanup Chain Reader * Fix QueryOne bindings * Update common and finish query filter remapping * Use keys for data types retrieval in chain reader * minor fix * Change evm dsl event filter naming to be less confusing * Change chain reader formatKey() to accept two params * Run make generate and rename chain reader testing contract * Remove addr from chReader dsl EventByWordFilter and EventByTopicFilter * Update chainlink-common * Fix chain reader binding changes and update common * Add a TODO for chain agnostic finality filter * Revert codec type key changes(belongs in a separate PR) * Update common * Merge branch 'develop' into chain-reader-event-querying2 * update common * generate log poller assets * Revert forge-std changes to match develop * Revert accidental generated wrapper changes --------- Co-authored-by: Mateusz Sekara Co-authored-by: Awbrey Hughlett --- .../scripts/native_solc_compile_all_shared | 2 +- ...TestContract.sol => ChainReaderTester.sol} | 2 +- .../evm/forwarders/forwarder_manager.go | 2 +- core/chains/evm/logpoller/disabled.go | 31 +- core/chains/evm/logpoller/log_poller.go | 63 ++- core/chains/evm/logpoller/log_poller_test.go | 4 +- core/chains/evm/logpoller/mocks/log_poller.go | 130 ++++--- core/chains/evm/logpoller/observability.go | 26 +- core/chains/evm/logpoller/orm.go | 64 +-- core/chains/evm/logpoller/orm_test.go | 19 +- core/chains/evm/logpoller/query.go | 3 +- core/chains/evm/types/types.go | 7 + .../chain_reader_tester.go} | 368 +++++++++--------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/gethwrappers/go_generate.go | 2 +- .../ocr2keeper/evmregistry/v21/registry.go | 6 +- .../v21/registry_check_pipeline_test.go | 5 +- .../evmregistry/v21/registry_test.go | 15 +- .../evmregistry/v21/upkeepstate/scanner.go | 3 +- .../ocr2vrf/coordinator/coordinator.go | 4 +- .../ocr2vrf/coordinator/coordinator_test.go | 17 +- core/services/relay/evm/binding.go | 2 + core/services/relay/evm/chain_reader.go | 131 +++++-- core/services/relay/evm/chain_reader_test.go | 34 +- core/services/relay/evm/codec_test.go | 8 +- core/services/relay/evm/dsl.go | 96 +++++ core/services/relay/evm/event_binding.go | 70 +++- core/services/relay/evm/method_binding.go | 15 +- core/services/relay/evm/pgparser.go | 36 ++ core/services/relay/evm/types/types.go | 6 + .../vrf/v2/listener_v2_log_listener.go | 6 +- 31 files changed, 762 insertions(+), 417 deletions(-) rename contracts/src/v0.8/shared/test/helpers/{ChainReaderTestContract.sol => ChainReaderTester.sol} (99%) rename core/gethwrappers/generated/{chain_reader_example/chain_reader_example.go => chain_reader_tester/chain_reader_tester.go} (73%) create mode 100644 core/services/relay/evm/dsl.go create mode 100644 core/services/relay/evm/pgparser.go diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared index eeaa9902346..c72e30b42d3 100755 --- a/contracts/scripts/native_solc_compile_all_shared +++ b/contracts/scripts/native_solc_compile_all_shared @@ -32,4 +32,4 @@ compileContract shared/token/ERC677/BurnMintERC677.sol compileContract shared/token/ERC677/LinkToken.sol compileContract shared/mocks/WERC20Mock.sol compileContract vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol -compileContract shared/test/helpers/ChainReaderTestContract.sol +compileContract shared/test/helpers/ChainReaderTester.sol diff --git a/contracts/src/v0.8/shared/test/helpers/ChainReaderTestContract.sol b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol similarity index 99% rename from contracts/src/v0.8/shared/test/helpers/ChainReaderTestContract.sol rename to contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol index 217901c1901..2cc0c44c451 100644 --- a/contracts/src/v0.8/shared/test/helpers/ChainReaderTestContract.sol +++ b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol @@ -22,7 +22,7 @@ struct InnerTestStruct { string S; } -contract LatestValueHolder { +contract ChainReaderTester { event Triggered( int32 indexed field, string differentField, diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index 3f09d9b7679..68015229307 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -253,7 +253,7 @@ func (f *FwdMgr) runLoop() { f.latestBlock, []common.Hash{authChangedTopic}, addrs, - evmlogpoller.Confirmations(f.cfg.FinalityDepth()), + evmtypes.Confirmations(f.cfg.FinalityDepth()), ) if err != nil { f.logger.Errorw("Failed to retrieve latest log round", "err", err) diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go index 6f95b9c55da..3a1e4ba4fe6 100644 --- a/core/chains/evm/logpoller/disabled.go +++ b/core/chains/evm/logpoller/disabled.go @@ -6,6 +6,9 @@ import ( "github.com/ethereum/go-ethereum/common" pkgerrors "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) var ( @@ -59,15 +62,15 @@ func (disabled) LogsWithSigs(ctx context.Context, start, end int64, eventSigs [] return nil, ErrDisabled } -func (disabled) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (disabled) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) { return nil, ErrDisabled } -func (disabled) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) ([]Log, error) { +func (disabled) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (disabled) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (disabled) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } @@ -79,42 +82,46 @@ func (d disabled) IndexedLogsByTxHash(ctx context.Context, eventSig common.Hash, return nil, ErrDisabled } -func (disabled) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (disabled) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (disabled) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (disabled) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (disabled) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (disabled) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (disabled) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (disabled) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (d disabled) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs Confirmations) ([]Log, error) { +func (d disabled) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (d disabled) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, time time.Time, confs Confirmations) ([]Log, error) { +func (d disabled) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, time time.Time, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (d disabled) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (d disabled) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } -func (d disabled) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (d disabled) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) { return 0, ErrDisabled } -func (d disabled) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (d disabled) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return nil, ErrDisabled } +func (d disabled) FilteredLogs(_ query.KeyFilter, _ query.LimitAndSort) ([]Log, error) { + return nil, nil +} + func (d disabled) FindLCA(ctx context.Context) (*LogPollerBlock, error) { return nil, ErrDisabled } diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index cd26889627f..b1d7d1da623 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -24,9 +24,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -50,30 +50,25 @@ type LogPoller interface { // General querying Logs(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address) ([]Log, error) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]Log, error) - LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, time time.Time, confs Confirmations) ([]Log, error) - LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) - LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) ([]Log, error) - LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) + LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, time time.Time, confs evmtypes.Confirmations) ([]Log, error) + LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) + LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) ([]Log, error) + LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) // Content based querying - IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) + IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) IndexedLogsByBlockRange(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]Log, error) - IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) + IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) IndexedLogsByTxHash(ctx context.Context, eventSig common.Hash, address common.Address, txHash common.Hash) ([]Log, error) - IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) - IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs Confirmations) ([]Log, error) - IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs Confirmations) ([]Log, error) - LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) - LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) - LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) -} + IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) + IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) + IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs evmtypes.Confirmations) ([]Log, error) + LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) + LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) + LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) -type Confirmations int - -const ( - Finalized = Confirmations(-1) - Unconfirmed = Confirmations(0) -) + FilteredLogs(filter query.KeyFilter, limitAndSrt query.LimitAndSort) ([]Log, error) +} type LogPollerTest interface { LogPoller @@ -1116,12 +1111,12 @@ func (lp *logPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSi return lp.orm.SelectLogsWithSigs(ctx, start, end, address, eventSigs) } -func (lp *logPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, after time.Time, confs Confirmations) ([]Log, error) { +func (lp *logPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectLogsCreatedAfter(ctx, address, eventSig, after, confs) } // IndexedLogs finds all the logs that have a topic value in topicValues at index topicIndex. -func (lp *logPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectIndexedLogs(ctx, address, eventSig, topicIndex, topicValues, confs) } @@ -1130,7 +1125,7 @@ func (lp *logPoller) IndexedLogsByBlockRange(ctx context.Context, start, end int return lp.orm.SelectIndexedLogsByBlockRange(ctx, start, end, address, eventSig, topicIndex, topicValues) } -func (lp *logPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (lp *logPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectIndexedLogsCreatedAfter(ctx, address, eventSig, topicIndex, topicValues, after, confs) } @@ -1139,22 +1134,22 @@ func (lp *logPoller) IndexedLogsByTxHash(ctx context.Context, eventSig common.Ha } // LogsDataWordGreaterThan note index is 0 based. -func (lp *logPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectLogsDataWordGreaterThan(ctx, address, eventSig, wordIndex, wordValueMin, confs) } // LogsDataWordRange note index is 0 based. -func (lp *logPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectLogsDataWordRange(ctx, address, eventSig, wordIndex, wordValueMin, wordValueMax, confs) } // IndexedLogsTopicGreaterThan finds all the logs that have a topic value greater than topicValueMin at index topicIndex. // Only works for integer topics. -func (lp *logPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectIndexedLogsTopicGreaterThan(ctx, address, eventSig, topicIndex, topicValueMin, confs) } -func (lp *logPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectIndexedLogsTopicRange(ctx, address, eventSig, topicIndex, topicValueMin, topicValueMax, confs) } @@ -1174,15 +1169,15 @@ func (lp *logPoller) BlockByNumber(ctx context.Context, n int64) (*LogPollerBloc } // LatestLogByEventSigWithConfs finds the latest log that has confs number of blocks on top of the log. -func (lp *logPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (lp *logPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) { return lp.orm.SelectLatestLogByEventSigWithConfs(ctx, eventSig, address, confs) } -func (lp *logPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) ([]Log, error) { +func (lp *logPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectLatestLogEventSigsAddrsWithConfs(ctx, fromBlock, addresses, eventSigs, confs) } -func (lp *logPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (lp *logPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) { return lp.orm.SelectLatestBlockByEventSigsAddrsWithConfs(ctx, fromBlock, eventSigs, addresses, confs) } @@ -1195,7 +1190,7 @@ func (lp *logPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, f // // This function is particularly useful for filtering logs by data word values and their positions within the event data. // It returns an empty slice if no logs match the provided criteria. -func (lp *logPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (lp *logPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectLogsDataWordBetween(ctx, address, eventSig, wordIndexMin, wordIndexMax, wordValue, confs) } @@ -1420,7 +1415,7 @@ func validateBlockResponse(r rpc.BatchElem) (*evmtypes.Head, error) { // // For example, query to retrieve unfulfilled requests by querying request log events without matching fulfillment log events. // The order of events is not significant. Both logs must be inside the block range and have the minimum number of confirmations -func (lp *logPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs Confirmations) ([]Log, error) { +func (lp *logPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA, eventSigB common.Hash, topicIndex int, fromBlock, toBlock int64, confs evmtypes.Confirmations) ([]Log, error) { return lp.orm.SelectIndexedLogsWithSigsExcluding(ctx, eventSigA, eventSigB, topicIndex, address, fromBlock, toBlock, confs) } @@ -1526,3 +1521,7 @@ func EvmWord(i uint64) common.Hash { binary.BigEndian.PutUint64(b, i) return common.BytesToHash(b) } + +func (lp *logPoller) FilteredLogs(queryFilter query.KeyFilter, sortAndLimit query.LimitAndSort) ([]Log, error) { + return lp.orm.FilteredLogs(queryFilter, sortAndLimit) +} diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 097c6f9eef2..6ef16921503 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -1678,7 +1678,7 @@ func Test_PollAndQueryFinalizedBlocks(t *testing.T) { th.EmitterAddress1, 0, common.Hash{}, - logpoller.Finalized, + evmtypes.Finalized, ) require.NoError(t, err) require.Len(t, finalizedLogs, firstBatchLen, fmt.Sprintf("len(finalizedLogs) = %d, should have been %d", len(finalizedLogs), firstBatchLen)) @@ -1690,7 +1690,7 @@ func Test_PollAndQueryFinalizedBlocks(t *testing.T) { th.EmitterAddress1, 0, common.Hash{}, - logpoller.Confirmations(numberOfConfirmations), + evmtypes.Confirmations(numberOfConfirmations), ) require.NoError(t, err) require.Len(t, logsByConfs, firstBatchLen+secondBatchLen-numberOfConfirmations) diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index ef3f4dbd428..e30aac56c8b 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -11,7 +11,11 @@ import ( mock "github.com/stretchr/testify/mock" + query "github.com/smartcontractkit/chainlink-common/pkg/types/query" + time "time" + + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) // LogPoller is an autogenerated mock type for the LogPoller type @@ -55,6 +59,36 @@ func (_m *LogPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) return r0 } +// FilteredLogs provides a mock function with given fields: filter, limitAndSrt +func (_m *LogPoller) FilteredLogs(filter query.KeyFilter, limitAndSrt query.LimitAndSort) ([]logpoller.Log, error) { + ret := _m.Called(filter, limitAndSrt) + + if len(ret) == 0 { + panic("no return value specified for FilteredLogs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(query.KeyFilter, query.LimitAndSort) ([]logpoller.Log, error)); ok { + return rf(filter, limitAndSrt) + } + if rf, ok := ret.Get(0).(func(query.KeyFilter, query.LimitAndSort) []logpoller.Log); ok { + r0 = rf(filter, limitAndSrt) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(query.KeyFilter, query.LimitAndSort) error); ok { + r1 = rf(filter, limitAndSrt) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FindLCA provides a mock function with given fields: ctx func (_m *LogPoller) FindLCA(ctx context.Context) (*logpoller.LogPollerBlock, error) { ret := _m.Called(ctx) @@ -192,7 +226,7 @@ func (_m *LogPoller) Healthy() error { } // IndexedLogs provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValues, confs -func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, topicIndex, topicValues, confs) if len(ret) == 0 { @@ -201,10 +235,10 @@ func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, addr var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, topicIndex, topicValues, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, topicIndex, topicValues, confs) } else { if ret.Get(0) != nil { @@ -212,7 +246,7 @@ func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, addr } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, topicIndex, topicValues, confs) } else { r1 = ret.Error(1) @@ -282,7 +316,7 @@ func (_m *LogPoller) IndexedLogsByTxHash(ctx context.Context, eventSig common.Ha } // IndexedLogsCreatedAfter provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValues, after, confs -func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, topicIndex, topicValues, after, confs) if len(ret) == 0 { @@ -291,10 +325,10 @@ func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig commo var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) } else { if ret.Get(0) != nil { @@ -302,7 +336,7 @@ func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig commo } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) } else { r1 = ret.Error(1) @@ -312,7 +346,7 @@ func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig commo } // IndexedLogsTopicGreaterThan provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValueMin, confs -func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, topicIndex, topicValueMin, confs) if len(ret) == 0 { @@ -321,10 +355,10 @@ func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig c var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) } else { if ret.Get(0) != nil { @@ -332,7 +366,7 @@ func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig c } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) } else { r1 = ret.Error(1) @@ -342,7 +376,7 @@ func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig c } // IndexedLogsTopicRange provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs -func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) if len(ret) == 0 { @@ -351,10 +385,10 @@ func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common. var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) } else { if ret.Get(0) != nil { @@ -362,7 +396,7 @@ func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common. } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) } else { r1 = ret.Error(1) @@ -372,7 +406,7 @@ func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common. } // IndexedLogsWithSigsExcluding provides a mock function with given fields: ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs -func (_m *LogPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA common.Hash, eventSigB common.Hash, topicIndex int, fromBlock int64, toBlock int64, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA common.Hash, eventSigB common.Hash, topicIndex int, fromBlock int64, toBlock int64, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) if len(ret) == 0 { @@ -381,10 +415,10 @@ func (_m *LogPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address c var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) } else { if ret.Get(0) != nil { @@ -392,7 +426,7 @@ func (_m *LogPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address c } } - if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) error); ok { r1 = rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) } else { r1 = ret.Error(1) @@ -430,7 +464,7 @@ func (_m *LogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, } // LatestBlockByEventSigsAddrsWithConfs provides a mock function with given fields: ctx, fromBlock, eventSigs, addresses, confs -func (_m *LogPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs logpoller.Confirmations) (int64, error) { +func (_m *LogPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations) (int64, error) { ret := _m.Called(ctx, fromBlock, eventSigs, addresses, confs) if len(ret) == 0 { @@ -439,16 +473,16 @@ func (_m *LogPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, f var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) (int64, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) (int64, error)); ok { return rf(ctx, fromBlock, eventSigs, addresses, confs) } - if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) int64); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) int64); ok { r0 = rf(ctx, fromBlock, eventSigs, addresses, confs) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) error); ok { r1 = rf(ctx, fromBlock, eventSigs, addresses, confs) } else { r1 = ret.Error(1) @@ -458,7 +492,7 @@ func (_m *LogPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, f } // LatestLogByEventSigWithConfs provides a mock function with given fields: ctx, eventSig, address, confs -func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs logpoller.Confirmations) (*logpoller.Log, error) { +func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs types.Confirmations) (*logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, confs) if len(ret) == 0 { @@ -467,10 +501,10 @@ func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig var r0 *logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, logpoller.Confirmations) (*logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, types.Confirmations) (*logpoller.Log, error)); ok { return rf(ctx, eventSig, address, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, logpoller.Confirmations) *logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, types.Confirmations) *logpoller.Log); ok { r0 = rf(ctx, eventSig, address, confs) } else { if ret.Get(0) != nil { @@ -478,7 +512,7 @@ func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, confs) } else { r1 = ret.Error(1) @@ -488,7 +522,7 @@ func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig } // LatestLogEventSigsAddrsWithConfs provides a mock function with given fields: ctx, fromBlock, eventSigs, addresses, confs -func (_m *LogPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, fromBlock, eventSigs, addresses, confs) if len(ret) == 0 { @@ -497,10 +531,10 @@ func (_m *LogPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromB var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, fromBlock, eventSigs, addresses, confs) } - if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, fromBlock, eventSigs, addresses, confs) } else { if ret.Get(0) != nil { @@ -508,7 +542,7 @@ func (_m *LogPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromB } } - if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) error); ok { r1 = rf(ctx, fromBlock, eventSigs, addresses, confs) } else { r1 = ret.Error(1) @@ -548,7 +582,7 @@ func (_m *LogPoller) Logs(ctx context.Context, start int64, end int64, eventSig } // LogsCreatedAfter provides a mock function with given fields: ctx, eventSig, address, _a3, confs -func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, _a3 time.Time, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, _a3 time.Time, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, _a3, confs) if len(ret) == 0 { @@ -557,10 +591,10 @@ func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, _a3, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, _a3, confs) } else { if ret.Get(0) != nil { @@ -568,7 +602,7 @@ func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, time.Time, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, _a3, confs) } else { r1 = ret.Error(1) @@ -578,7 +612,7 @@ func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, } // LogsDataWordBetween provides a mock function with given fields: ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs -func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) if len(ret) == 0 { @@ -587,10 +621,10 @@ func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Ha var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) } else { if ret.Get(0) != nil { @@ -598,7 +632,7 @@ func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Ha } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) } else { r1 = ret.Error(1) @@ -608,7 +642,7 @@ func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Ha } // LogsDataWordGreaterThan provides a mock function with given fields: ctx, eventSig, address, wordIndex, wordValueMin, confs -func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, wordIndex, wordValueMin, confs) if len(ret) == 0 { @@ -617,10 +651,10 @@ func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig commo var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) } else { if ret.Get(0) != nil { @@ -628,7 +662,7 @@ func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig commo } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) } else { r1 = ret.Error(1) @@ -638,7 +672,7 @@ func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig commo } // LogsDataWordRange provides a mock function with given fields: ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs -func (_m *LogPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, wordValueMax common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (_m *LogPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, wordValueMax common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) if len(ret) == 0 { @@ -647,10 +681,10 @@ func (_m *LogPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { return rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) []logpoller.Log); ok { r0 = rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) } else { if ret.Get(0) != nil { @@ -658,7 +692,7 @@ func (_m *LogPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, logpoller.Confirmations) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) error); ok { r1 = rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) } else { r1 = ret.Error(1) diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go index 8f3cdfe185e..361b8610905 100644 --- a/core/chains/evm/logpoller/observability.go +++ b/core/chains/evm/logpoller/observability.go @@ -9,6 +9,8 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) @@ -157,7 +159,7 @@ func (o *ObservedORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumb }) } -func (o *ObservedORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (o *ObservedORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) { return withObservedQuery(o, "SelectLatestLogByEventSigWithConfs", func() (*Log, error) { return o.ORM.SelectLatestLogByEventSigWithConfs(ctx, eventSig, address, confs) }) @@ -169,13 +171,13 @@ func (o *ObservedORM) SelectLogsWithSigs(ctx context.Context, start, end int64, }) } -func (o *ObservedORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectLogsCreatedAfter", func() ([]Log, error) { return o.ORM.SelectLogsCreatedAfter(ctx, address, eventSig, after, confs) }) } -func (o *ObservedORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectIndexedLogs", func() ([]Log, error) { return o.ORM.SelectIndexedLogs(ctx, address, eventSig, topicIndex, topicValues, confs) }) @@ -187,13 +189,13 @@ func (o *ObservedORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, }) } -func (o *ObservedORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectIndexedLogsCreatedAfter", func() ([]Log, error) { return o.ORM.SelectIndexedLogsCreatedAfter(ctx, address, eventSig, topicIndex, topicValues, after, confs) }) } -func (o *ObservedORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectIndexedLogsWithSigsExcluding", func() ([]Log, error) { return o.ORM.SelectIndexedLogsWithSigsExcluding(ctx, sigA, sigB, topicIndex, address, startBlock, endBlock, confs) }) @@ -217,43 +219,43 @@ func (o *ObservedORM) GetBlocksRange(ctx context.Context, start int64, end int64 }) } -func (o *ObservedORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectLatestLogEventSigsAddrsWithConfs", func() ([]Log, error) { return o.ORM.SelectLatestLogEventSigsAddrsWithConfs(ctx, fromBlock, addresses, eventSigs, confs) }) } -func (o *ObservedORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (o *ObservedORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) { return withObservedQuery(o, "SelectLatestBlockByEventSigsAddrsWithConfs", func() (int64, error) { return o.ORM.SelectLatestBlockByEventSigsAddrsWithConfs(ctx, fromBlock, eventSigs, addresses, confs) }) } -func (o *ObservedORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectLogsDataWordRange", func() ([]Log, error) { return o.ORM.SelectLogsDataWordRange(ctx, address, eventSig, wordIndex, wordValueMin, wordValueMax, confs) }) } -func (o *ObservedORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectLogsDataWordGreaterThan", func() ([]Log, error) { return o.ORM.SelectLogsDataWordGreaterThan(ctx, address, eventSig, wordIndex, wordValueMin, confs) }) } -func (o *ObservedORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectLogsDataWordBetween", func() ([]Log, error) { return o.ORM.SelectLogsDataWordBetween(ctx, address, eventSig, wordIndexMin, wordIndexMax, wordValue, confs) }) } -func (o *ObservedORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectIndexedLogsTopicGreaterThan", func() ([]Log, error) { return o.ORM.SelectIndexedLogsTopicGreaterThan(ctx, address, eventSig, topicIndex, topicValueMin, confs) }) } -func (o *ObservedORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *ObservedORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { return withObservedQueryAndResults(o, "SelectIndexedLogsTopicRange", func() ([]Log, error) { return o.ORM.SelectIndexedLogsTopicRange(ctx, address, eventSig, topicIndex, topicValueMin, topicValueMax, confs) }) diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 5084e0329a7..3cd8db74849 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -12,7 +12,10 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -42,22 +45,24 @@ type ORM interface { SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) ([]Log, error) - SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) - SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) - SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) - SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) + SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) + SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) + SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs evmtypes.Confirmations) ([]Log, error) + SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([]Log, error) - SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) + SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) SelectIndexedLogsByBlockRange(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash) ([]Log, error) - SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) - SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) - SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) - SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) + SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) + SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) + SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) + SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs evmtypes.Confirmations) ([]Log, error) SelectIndexedLogsByTxHash(ctx context.Context, address common.Address, eventSig common.Hash, txHash common.Hash) ([]Log, error) - SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) - SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) - SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) + SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) + SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) + SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) + // FilteredLogs accepts chainlink-common filtering DSL. + FilteredLogs(filter query.KeyFilter, sortAndLimit query.LimitAndSort) ([]Log, error) } type DSORM struct { @@ -210,7 +215,7 @@ func (o *DSORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int return &b, nil } -func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs evmtypes.Confirmations) (*Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withConfs(confs). toArgs() @@ -473,7 +478,7 @@ func (o *DSORM) SelectLogs(ctx context.Context, start, end int64, address common } // SelectLogsCreatedAfter finds logs created after some timestamp. -func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -564,7 +569,7 @@ func (o *DSORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L } // SelectLatestLogEventSigsAddrsWithConfs finds the latest log by (address, event) combination that matches a list of Addresses and list of events -func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddressArray(addresses). withEventSigArray(eventSigs). @@ -600,7 +605,7 @@ func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, from } // SelectLatestBlockByEventSigsAddrsWithConfs finds the latest block number that matches a list of Addresses and list of events. It returns 0 if there is no matching block -func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs evmtypes.Confirmations) (int64, error) { args, err := newQueryArgs(o.chainID). withEventSigArray(eventSigs). withAddressArray(addresses). @@ -630,7 +635,7 @@ func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, return blockNumber, nil } -func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -662,7 +667,7 @@ func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Addr return logs, nil } -func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -693,7 +698,7 @@ func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address commo return logs, nil } -func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndexMin(wordIndexMin). withWordIndexMax(wordIndexMax). @@ -725,7 +730,7 @@ func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Ad return logs, nil } -func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -756,7 +761,7 @@ func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address c return logs, nil } -func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -789,7 +794,7 @@ func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common. return logs, nil } -func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValues(topicValues). @@ -854,7 +859,7 @@ func (o *DSORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end in return logs, nil } -func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -918,8 +923,8 @@ func (o *DSORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad return logs, nil } -// SelectIndexedLogsWithSigsExcluding query's for logs that have signature A and exclude logs that have a corresponding signature B, matching is done based on the topic index both logs should be inside the block range and have the minimum number of confirmations -func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { +// SelectIndexedLogsWithSigsExcluding query's for logs that have signature A and exclude logs that have a corresponding signature B, matching is done based on the topic index both logs should be inside the block range and have the minimum number of evmtypes.Confirmations +func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs evmtypes.Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddress(address). withTopicIndex(topicIndex). @@ -965,8 +970,13 @@ func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si return logs, nil } -func nestedBlockNumberQuery(confs Confirmations) string { - if confs == Finalized { +func (o *DSORM) FilteredLogs(_ query.KeyFilter, _ query.LimitAndSort) ([]Log, error) { + //TODO implement me + panic("implement me") +} + +func nestedBlockNumberQuery(confs evmtypes.Confirmations) string { + if confs == evmtypes.Finalized { return ` (SELECT finalized_block_number FROM evm.log_poller_blocks diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index c89a39aa6b4..7e6ce9aada2 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" @@ -1245,7 +1246,7 @@ func TestSelectLatestBlockNumberEventSigsAddrsWithConfs(t *testing.T) { name string events []common.Hash addrs []common.Address - confs logpoller.Confirmations + confs evmtypes.Confirmations fromBlock int64 expectedBlockNumber int64 }{ @@ -1277,7 +1278,7 @@ func TestSelectLatestBlockNumberEventSigsAddrsWithConfs(t *testing.T) { name: "only finalized log is picked", events: []common.Hash{event1, event2}, addrs: []common.Address{address1, address2}, - confs: logpoller.Finalized, + confs: evmtypes.Finalized, fromBlock: 0, expectedBlockNumber: 1, }, @@ -1350,7 +1351,7 @@ func TestSelectLogsCreatedAfter(t *testing.T) { tests := []struct { name string - confs logpoller.Confirmations + confs evmtypes.Confirmations after time.Time expectedLogs []expectedLog }{ @@ -1395,7 +1396,7 @@ func TestSelectLogsCreatedAfter(t *testing.T) { }, { name: "returns only finalized log", - confs: logpoller.Finalized, + confs: evmtypes.Finalized, after: block1ts, expectedLogs: []expectedLog{ {block: 2, log: 1}, @@ -1439,7 +1440,7 @@ func TestNestedLogPollerBlocksQuery(t *testing.T) { })) // Empty logs when block are not persisted - logs, err := th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, logpoller.Unconfirmed) + logs, err := th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, evmtypes.Unconfirmed) require.NoError(t, err) require.Len(t, logs, 0) @@ -1447,12 +1448,12 @@ func TestNestedLogPollerBlocksQuery(t *testing.T) { require.NoError(t, th.ORM.InsertBlock(ctx, utils.RandomHash(), 10, time.Now(), 0)) // Check if query actually works well with provided dataset - logs, err = th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, logpoller.Unconfirmed) + logs, err = th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, evmtypes.Unconfirmed) require.NoError(t, err) require.Len(t, logs, 1) // Empty logs when number of confirmations is too deep - logs, err = th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, logpoller.Confirmations(4)) + logs, err = th.ORM.SelectIndexedLogs(ctx, address, event, 1, []common.Hash{event}, evmtypes.Confirmations(4)) require.NoError(t, err) require.Len(t, logs, 0) } @@ -1641,7 +1642,7 @@ func TestSelectLogsDataWordBetween(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - logs, err1 := th.ORM.SelectLogsDataWordBetween(ctx, address, eventSig, 0, 1, logpoller.EvmWord(tt.wordValue), logpoller.Unconfirmed) + logs, err1 := th.ORM.SelectLogsDataWordBetween(ctx, address, eventSig, 0, 1, logpoller.EvmWord(tt.wordValue), evmtypes.Unconfirmed) assert.NoError(t, err1) assert.Len(t, logs, len(tt.expectedLogs)) @@ -1698,7 +1699,7 @@ func Benchmark_LogsDataWordBetween(b *testing.B) { 2, 3, logpoller.EvmWord(uint64(numberOfReports*numberOfMessagesPerReport/2)), // Pick the middle report - logpoller.Unconfirmed, + evmtypes.Unconfirmed, ) assert.NoError(b, err) assert.Len(b, logs, 1) diff --git a/core/chains/evm/logpoller/query.go b/core/chains/evm/logpoller/query.go index f9d2c45bce1..244552dbec8 100644 --- a/core/chains/evm/logpoller/query.go +++ b/core/chains/evm/logpoller/query.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -104,7 +105,7 @@ func (q *queryArgs) withWordValue(wordValue common.Hash) *queryArgs { return q.withCustomHashArg("word_value", wordValue) } -func (q *queryArgs) withConfs(confs Confirmations) *queryArgs { +func (q *queryArgs) withConfs(confs evmtypes.Confirmations) *queryArgs { return q.withCustomArg("confs", confs) } diff --git a/core/chains/evm/types/types.go b/core/chains/evm/types/types.go index 2a6b5eb0ab4..57a53bce67a 100644 --- a/core/chains/evm/types/types.go +++ b/core/chains/evm/types/types.go @@ -225,6 +225,13 @@ func (r *Receipt) GetBlockHash() common.Hash { return r.BlockHash } +type Confirmations int + +const ( + Finalized = Confirmations(-1) + Unconfirmed = Confirmations(0) +) + // Log represents a contract log event. // // Copied from go-ethereum: https://github.com/ethereum/go-ethereum/blob/ce9a289fa48e0d2593c4aaa7e207c8a5dd3eaa8a/core/types/log.go diff --git a/core/gethwrappers/generated/chain_reader_example/chain_reader_example.go b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go similarity index 73% rename from core/gethwrappers/generated/chain_reader_example/chain_reader_example.go rename to core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go index f6dce0bb6c3..17923820796 100644 --- a/core/gethwrappers/generated/chain_reader_example/chain_reader_example.go +++ b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package chain_reader_example +package chain_reader_tester import ( "errors" @@ -51,17 +51,17 @@ type TestStruct struct { NestedStruct MidLevelTestStruct } -var LatestValueHolderMetaData = &bind.MetaData{ +var ChainReaderTesterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"Triggered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"fieldHash\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"TriggeredEventWithDynamicTopic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"TriggeredWithFourTopics\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"addTestStruct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDifferentPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"getElementAtIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSliceValue\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"returnSeen\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"triggerWithFourTopics\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a91820291021990921691909117905561176c806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80637f002d6711610076578063dbfd73321161005b578063dbfd73321461013e578063ef4e1ced14610151578063f6f871c81461015857600080fd5b80637f002d671461010e578063ab5e0b381461012157600080fd5b80632c45576f146100a85780633272b66c146100d157806349eac2ac146100e6578063679004a4146100f9575b600080fd5b6100bb6100b6366004610baa565b61016b565b6040516100c89190610d09565b60405180910390f35b6100e46100df366004610e48565b610446565b005b6100e46100f4366004610f5d565b61049b565b61010161079e565b6040516100c8919061104f565b6100e461011c366004610f5d565b61082a565b6107c65b60405167ffffffffffffffff90911681526020016100c8565b6100e461014c36600461109d565b610881565b6003610125565b6100bb610166366004610f5d565b6108be565b6101736109c7565b60006101806001846110e0565b815481106101905761019061111a565b6000918252602091829020604080516101008101909152600a90920201805460030b825260018101805492939192918401916101cb90611149565b80601f01602080910402602001604051908101604052809291908181526020018280546101f790611149565b80156102445780601f1061021957610100808354040283529160200191610244565b820191906000526020600020905b81548152906001019060200180831161022757829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161027957505050928452505050600482015473ffffffffffffffffffffffffffffffffffffffff16602080830191909152600583018054604080518285028101850182528281529401939283018282801561033257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610307575b5050509183525050600682015460170b6020808301919091526040805180820182526007808601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001683528351808501855260088801805490930b815260098801805495909701969395919486830194919392840191906103b790611149565b80601f01602080910402602001604051908101604052809291908181526020018280546103e390611149565b80156104305780601f1061040557610100808354040283529160200191610430565b820191906000526020600020905b81548152906001019060200180831161041357829003601f168201915b5050509190925250505090525090525092915050565b8181604051610456929190611196565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c67838360405161048f9291906111ef565b60405180910390a25050565b60006040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b602082015260400161058d846112ec565b905281546001808201845560009384526020938490208351600a9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9093169290921782559282015191929091908201906105f39082611446565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560608201516106419060038301906020610a16565b5060808201516004820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905560a082015180516106a8916005840191602090910190610aa9565b5060c08201516006820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560e082015180516007830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516008860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117815591810151909190600986019061078b9082611446565b5050505050505050505050505050505050565b6060600180548060200260200160405190810160405280929190818152602001828054801561082057602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff16815260200190600801906020826007010492830192600103820291508084116107db5790505b5050505050905090565b8960030b7f7188419dcd8b51877b71766f075f3626586c0ff190e7d056aa65ce9acb649a3d8a8a8a8a8a8a8a8a8a60405161086d999897969594939291906116a5565b60405180910390a250505050505050505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b6108c66109c7565b6040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b60208201526040016109b6846112ec565b90529b9a5050505050505050505050565b60408051610100810182526000808252606060208301819052928201529081016109ef610b23565b8152600060208201819052606060408301819052820152608001610a11610b42565b905290565b600183019183908215610a995791602002820160005b83821115610a6a57835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610a2c565b8015610a975782816101000a81549060ff0219169055600101602081600001049283019260010302610a6a565b505b50610aa5929150610b95565b5090565b828054828255906000526020600020908101928215610a99579160200282015b82811115610a9957825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610ac9565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610a116040518060400160405280600060070b8152602001606081525090565b5b80821115610aa55760008155600101610b96565b600060208284031215610bbc57600080fd5b5035919050565b6000815180845260005b81811015610be957602081850181015186830182015201610bcd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b8060005b6020808210610c3a5750610c51565b825160ff1685529384019390910190600101610c2b565b50505050565b600081518084526020808501945080840160005b83811015610c9d57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610c6b565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b60408501526020810151905060406060850152610d016080850182610bc3565b949350505050565b60208152610d1d60208201835160030b9052565b600060208301516104e0806040850152610d3b610500850183610bc3565b91506040850151610d51606086018260ff169052565b506060850151610d646080860182610c27565b50608085015173ffffffffffffffffffffffffffffffffffffffff1661048085015260a08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840381016104a0870152610dc18483610c57565b935060c08701519150610dda6104c087018360170b9052565b60e0870151915080868503018387015250610df58382610ca8565b9695505050505050565b60008083601f840112610e1157600080fd5b50813567ffffffffffffffff811115610e2957600080fd5b602083019150836020828501011115610e4157600080fd5b9250929050565b60008060208385031215610e5b57600080fd5b823567ffffffffffffffff811115610e7257600080fd5b610e7e85828601610dff565b90969095509350505050565b8035600381900b8114610e9c57600080fd5b919050565b803560ff81168114610e9c57600080fd5b806104008101831015610ec457600080fd5b92915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e9c57600080fd5b60008083601f840112610f0057600080fd5b50813567ffffffffffffffff811115610f1857600080fd5b6020830191508360208260051b8501011115610e4157600080fd5b8035601781900b8114610e9c57600080fd5b600060408284031215610f5757600080fd5b50919050565b6000806000806000806000806000806104e08b8d031215610f7d57600080fd5b610f868b610e8a565b995060208b013567ffffffffffffffff80821115610fa357600080fd5b610faf8e838f01610dff565b909b509950899150610fc360408e01610ea1565b9850610fd28e60608f01610eb2565b9750610fe16104608e01610eca565b96506104808d0135915080821115610ff857600080fd5b6110048e838f01610eee565b90965094508491506110196104a08e01610f33565b93506104c08d013591508082111561103057600080fd5b5061103d8d828e01610f45565b9150509295989b9194979a5092959850565b6020808252825182820181905260009190848201906040850190845b8181101561109157835167ffffffffffffffff168352928401929184019160010161106b565b50909695505050505050565b6000806000606084860312156110b257600080fd5b6110bb84610e8a565b92506110c960208501610e8a565b91506110d760408501610e8a565b90509250925092565b81810381811115610ec4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061115d57607f821691505b602082108103610f57577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610d016020830184866111a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561125557611255611203565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156112a2576112a2611203565b604052919050565b80357fffff00000000000000000000000000000000000000000000000000000000000081168114610e9c57600080fd5b8035600781900b8114610e9c57600080fd5b6000604082360312156112fe57600080fd5b611306611232565b61130f836112aa565b815260208084013567ffffffffffffffff8082111561132d57600080fd5b81860191506040823603121561134257600080fd5b61134a611232565b611353836112da565b8152838301358281111561136657600080fd5b929092019136601f84011261137a57600080fd5b82358281111561138c5761138c611203565b6113bc857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161125b565b925080835236858286010111156113d257600080fd5b8085850186850137600090830185015280840191909152918301919091525092915050565b601f82111561144157600081815260208120601f850160051c8101602086101561141e5750805b601f850160051c820191505b8181101561143d5782815560010161142a565b5050505b505050565b815167ffffffffffffffff81111561146057611460611203565b6114748161146e8454611149565b846113f7565b602080601f8311600181146114c757600084156114915750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561143d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611514578886015182559484019460019091019084016114f5565b508582101561155057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8183526000602080850194508260005b85811015610c9d5773ffffffffffffffffffffffffffffffffffffffff61159683610eca565b1687529582019590820190600101611570565b7fffff0000000000000000000000000000000000000000000000000000000000006115d3826112aa565b168252600060208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261160d57600080fd5b60406020850152820161161f816112da565b60070b604085015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811261165c57600080fd5b0160208101903567ffffffffffffffff81111561167857600080fd5b80360382131561168757600080fd5b6040606086015261169c6080860182846111a6565b95945050505050565b60006104c08083526116ba8184018c8e6111a6565b9050602060ff808c1682860152604085018b60005b848110156116f457836116e183610ea1565b16835291840191908401906001016116cf565b505050505073ffffffffffffffffffffffffffffffffffffffff881661044084015282810361046084015261172a818789611560565b905061173c61048084018660170b9052565b8281036104a084015261174f81856115a9565b9c9b50505050505050505050505056fea164736f6c6343000813000a", } -var LatestValueHolderABI = LatestValueHolderMetaData.ABI +var ChainReaderTesterABI = ChainReaderTesterMetaData.ABI -var LatestValueHolderBin = LatestValueHolderMetaData.Bin +var ChainReaderTesterBin = ChainReaderTesterMetaData.Bin -func DeployLatestValueHolder(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LatestValueHolder, error) { - parsed, err := LatestValueHolderMetaData.GetAbi() +func DeployChainReaderTester(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChainReaderTester, error) { + parsed, err := ChainReaderTesterMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -69,132 +69,132 @@ func DeployLatestValueHolder(auth *bind.TransactOpts, backend bind.ContractBacke return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LatestValueHolderBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ChainReaderTesterBin), backend) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &LatestValueHolder{address: address, abi: *parsed, LatestValueHolderCaller: LatestValueHolderCaller{contract: contract}, LatestValueHolderTransactor: LatestValueHolderTransactor{contract: contract}, LatestValueHolderFilterer: LatestValueHolderFilterer{contract: contract}}, nil + return address, tx, &ChainReaderTester{address: address, abi: *parsed, ChainReaderTesterCaller: ChainReaderTesterCaller{contract: contract}, ChainReaderTesterTransactor: ChainReaderTesterTransactor{contract: contract}, ChainReaderTesterFilterer: ChainReaderTesterFilterer{contract: contract}}, nil } -type LatestValueHolder struct { +type ChainReaderTester struct { address common.Address abi abi.ABI - LatestValueHolderCaller - LatestValueHolderTransactor - LatestValueHolderFilterer + ChainReaderTesterCaller + ChainReaderTesterTransactor + ChainReaderTesterFilterer } -type LatestValueHolderCaller struct { +type ChainReaderTesterCaller struct { contract *bind.BoundContract } -type LatestValueHolderTransactor struct { +type ChainReaderTesterTransactor struct { contract *bind.BoundContract } -type LatestValueHolderFilterer struct { +type ChainReaderTesterFilterer struct { contract *bind.BoundContract } -type LatestValueHolderSession struct { - Contract *LatestValueHolder +type ChainReaderTesterSession struct { + Contract *ChainReaderTester CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type LatestValueHolderCallerSession struct { - Contract *LatestValueHolderCaller +type ChainReaderTesterCallerSession struct { + Contract *ChainReaderTesterCaller CallOpts bind.CallOpts } -type LatestValueHolderTransactorSession struct { - Contract *LatestValueHolderTransactor +type ChainReaderTesterTransactorSession struct { + Contract *ChainReaderTesterTransactor TransactOpts bind.TransactOpts } -type LatestValueHolderRaw struct { - Contract *LatestValueHolder +type ChainReaderTesterRaw struct { + Contract *ChainReaderTester } -type LatestValueHolderCallerRaw struct { - Contract *LatestValueHolderCaller +type ChainReaderTesterCallerRaw struct { + Contract *ChainReaderTesterCaller } -type LatestValueHolderTransactorRaw struct { - Contract *LatestValueHolderTransactor +type ChainReaderTesterTransactorRaw struct { + Contract *ChainReaderTesterTransactor } -func NewLatestValueHolder(address common.Address, backend bind.ContractBackend) (*LatestValueHolder, error) { - abi, err := abi.JSON(strings.NewReader(LatestValueHolderABI)) +func NewChainReaderTester(address common.Address, backend bind.ContractBackend) (*ChainReaderTester, error) { + abi, err := abi.JSON(strings.NewReader(ChainReaderTesterABI)) if err != nil { return nil, err } - contract, err := bindLatestValueHolder(address, backend, backend, backend) + contract, err := bindChainReaderTester(address, backend, backend, backend) if err != nil { return nil, err } - return &LatestValueHolder{address: address, abi: abi, LatestValueHolderCaller: LatestValueHolderCaller{contract: contract}, LatestValueHolderTransactor: LatestValueHolderTransactor{contract: contract}, LatestValueHolderFilterer: LatestValueHolderFilterer{contract: contract}}, nil + return &ChainReaderTester{address: address, abi: abi, ChainReaderTesterCaller: ChainReaderTesterCaller{contract: contract}, ChainReaderTesterTransactor: ChainReaderTesterTransactor{contract: contract}, ChainReaderTesterFilterer: ChainReaderTesterFilterer{contract: contract}}, nil } -func NewLatestValueHolderCaller(address common.Address, caller bind.ContractCaller) (*LatestValueHolderCaller, error) { - contract, err := bindLatestValueHolder(address, caller, nil, nil) +func NewChainReaderTesterCaller(address common.Address, caller bind.ContractCaller) (*ChainReaderTesterCaller, error) { + contract, err := bindChainReaderTester(address, caller, nil, nil) if err != nil { return nil, err } - return &LatestValueHolderCaller{contract: contract}, nil + return &ChainReaderTesterCaller{contract: contract}, nil } -func NewLatestValueHolderTransactor(address common.Address, transactor bind.ContractTransactor) (*LatestValueHolderTransactor, error) { - contract, err := bindLatestValueHolder(address, nil, transactor, nil) +func NewChainReaderTesterTransactor(address common.Address, transactor bind.ContractTransactor) (*ChainReaderTesterTransactor, error) { + contract, err := bindChainReaderTester(address, nil, transactor, nil) if err != nil { return nil, err } - return &LatestValueHolderTransactor{contract: contract}, nil + return &ChainReaderTesterTransactor{contract: contract}, nil } -func NewLatestValueHolderFilterer(address common.Address, filterer bind.ContractFilterer) (*LatestValueHolderFilterer, error) { - contract, err := bindLatestValueHolder(address, nil, nil, filterer) +func NewChainReaderTesterFilterer(address common.Address, filterer bind.ContractFilterer) (*ChainReaderTesterFilterer, error) { + contract, err := bindChainReaderTester(address, nil, nil, filterer) if err != nil { return nil, err } - return &LatestValueHolderFilterer{contract: contract}, nil + return &ChainReaderTesterFilterer{contract: contract}, nil } -func bindLatestValueHolder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := LatestValueHolderMetaData.GetAbi() +func bindChainReaderTester(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ChainReaderTesterMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_LatestValueHolder *LatestValueHolderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LatestValueHolder.Contract.LatestValueHolderCaller.contract.Call(opts, result, method, params...) +func (_ChainReaderTester *ChainReaderTesterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainReaderTester.Contract.ChainReaderTesterCaller.contract.Call(opts, result, method, params...) } -func (_LatestValueHolder *LatestValueHolderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LatestValueHolder.Contract.LatestValueHolderTransactor.contract.Transfer(opts) +func (_ChainReaderTester *ChainReaderTesterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainReaderTester.Contract.ChainReaderTesterTransactor.contract.Transfer(opts) } -func (_LatestValueHolder *LatestValueHolderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LatestValueHolder.Contract.LatestValueHolderTransactor.contract.Transact(opts, method, params...) +func (_ChainReaderTester *ChainReaderTesterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainReaderTester.Contract.ChainReaderTesterTransactor.contract.Transact(opts, method, params...) } -func (_LatestValueHolder *LatestValueHolderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LatestValueHolder.Contract.contract.Call(opts, result, method, params...) +func (_ChainReaderTester *ChainReaderTesterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainReaderTester.Contract.contract.Call(opts, result, method, params...) } -func (_LatestValueHolder *LatestValueHolderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LatestValueHolder.Contract.contract.Transfer(opts) +func (_ChainReaderTester *ChainReaderTesterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainReaderTester.Contract.contract.Transfer(opts) } -func (_LatestValueHolder *LatestValueHolderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LatestValueHolder.Contract.contract.Transact(opts, method, params...) +func (_ChainReaderTester *ChainReaderTesterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainReaderTester.Contract.contract.Transact(opts, method, params...) } -func (_LatestValueHolder *LatestValueHolderCaller) GetDifferentPrimitiveValue(opts *bind.CallOpts) (uint64, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) GetDifferentPrimitiveValue(opts *bind.CallOpts) (uint64, error) { var out []interface{} - err := _LatestValueHolder.contract.Call(opts, &out, "getDifferentPrimitiveValue") + err := _ChainReaderTester.contract.Call(opts, &out, "getDifferentPrimitiveValue") if err != nil { return *new(uint64), err @@ -206,17 +206,17 @@ func (_LatestValueHolder *LatestValueHolderCaller) GetDifferentPrimitiveValue(op } -func (_LatestValueHolder *LatestValueHolderSession) GetDifferentPrimitiveValue() (uint64, error) { - return _LatestValueHolder.Contract.GetDifferentPrimitiveValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterSession) GetDifferentPrimitiveValue() (uint64, error) { + return _ChainReaderTester.Contract.GetDifferentPrimitiveValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCallerSession) GetDifferentPrimitiveValue() (uint64, error) { - return _LatestValueHolder.Contract.GetDifferentPrimitiveValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterCallerSession) GetDifferentPrimitiveValue() (uint64, error) { + return _ChainReaderTester.Contract.GetDifferentPrimitiveValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCaller) GetElementAtIndex(opts *bind.CallOpts, i *big.Int) (TestStruct, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) GetElementAtIndex(opts *bind.CallOpts, i *big.Int) (TestStruct, error) { var out []interface{} - err := _LatestValueHolder.contract.Call(opts, &out, "getElementAtIndex", i) + err := _ChainReaderTester.contract.Call(opts, &out, "getElementAtIndex", i) if err != nil { return *new(TestStruct), err @@ -228,17 +228,17 @@ func (_LatestValueHolder *LatestValueHolderCaller) GetElementAtIndex(opts *bind. } -func (_LatestValueHolder *LatestValueHolderSession) GetElementAtIndex(i *big.Int) (TestStruct, error) { - return _LatestValueHolder.Contract.GetElementAtIndex(&_LatestValueHolder.CallOpts, i) +func (_ChainReaderTester *ChainReaderTesterSession) GetElementAtIndex(i *big.Int) (TestStruct, error) { + return _ChainReaderTester.Contract.GetElementAtIndex(&_ChainReaderTester.CallOpts, i) } -func (_LatestValueHolder *LatestValueHolderCallerSession) GetElementAtIndex(i *big.Int) (TestStruct, error) { - return _LatestValueHolder.Contract.GetElementAtIndex(&_LatestValueHolder.CallOpts, i) +func (_ChainReaderTester *ChainReaderTesterCallerSession) GetElementAtIndex(i *big.Int) (TestStruct, error) { + return _ChainReaderTester.Contract.GetElementAtIndex(&_ChainReaderTester.CallOpts, i) } -func (_LatestValueHolder *LatestValueHolderCaller) GetPrimitiveValue(opts *bind.CallOpts) (uint64, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) GetPrimitiveValue(opts *bind.CallOpts) (uint64, error) { var out []interface{} - err := _LatestValueHolder.contract.Call(opts, &out, "getPrimitiveValue") + err := _ChainReaderTester.contract.Call(opts, &out, "getPrimitiveValue") if err != nil { return *new(uint64), err @@ -250,17 +250,17 @@ func (_LatestValueHolder *LatestValueHolderCaller) GetPrimitiveValue(opts *bind. } -func (_LatestValueHolder *LatestValueHolderSession) GetPrimitiveValue() (uint64, error) { - return _LatestValueHolder.Contract.GetPrimitiveValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterSession) GetPrimitiveValue() (uint64, error) { + return _ChainReaderTester.Contract.GetPrimitiveValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCallerSession) GetPrimitiveValue() (uint64, error) { - return _LatestValueHolder.Contract.GetPrimitiveValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterCallerSession) GetPrimitiveValue() (uint64, error) { + return _ChainReaderTester.Contract.GetPrimitiveValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCaller) GetSliceValue(opts *bind.CallOpts) ([]uint64, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) GetSliceValue(opts *bind.CallOpts) ([]uint64, error) { var out []interface{} - err := _LatestValueHolder.contract.Call(opts, &out, "getSliceValue") + err := _ChainReaderTester.contract.Call(opts, &out, "getSliceValue") if err != nil { return *new([]uint64), err @@ -272,17 +272,17 @@ func (_LatestValueHolder *LatestValueHolderCaller) GetSliceValue(opts *bind.Call } -func (_LatestValueHolder *LatestValueHolderSession) GetSliceValue() ([]uint64, error) { - return _LatestValueHolder.Contract.GetSliceValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterSession) GetSliceValue() ([]uint64, error) { + return _ChainReaderTester.Contract.GetSliceValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCallerSession) GetSliceValue() ([]uint64, error) { - return _LatestValueHolder.Contract.GetSliceValue(&_LatestValueHolder.CallOpts) +func (_ChainReaderTester *ChainReaderTesterCallerSession) GetSliceValue() ([]uint64, error) { + return _ChainReaderTester.Contract.GetSliceValue(&_ChainReaderTester.CallOpts) } -func (_LatestValueHolder *LatestValueHolderCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { var out []interface{} - err := _LatestValueHolder.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) + err := _ChainReaderTester.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) if err != nil { return *new(TestStruct), err @@ -294,64 +294,64 @@ func (_LatestValueHolder *LatestValueHolderCaller) ReturnSeen(opts *bind.CallOpt } -func (_LatestValueHolder *LatestValueHolderSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _LatestValueHolder.Contract.ReturnSeen(&_LatestValueHolder.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _LatestValueHolder.Contract.ReturnSeen(&_LatestValueHolder.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.Contract.AddTestStruct(&_LatestValueHolder.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.Contract.AddTestStruct(&_LatestValueHolder.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.contract.Transact(opts, "triggerEvent", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerEvent", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerEvent(&_LatestValueHolder.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderTransactorSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerEvent(&_LatestValueHolder.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) } -func (_LatestValueHolder *LatestValueHolderTransactor) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) { - return _LatestValueHolder.contract.Transact(opts, "triggerEventWithDynamicTopic", field) +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerEventWithDynamicTopic", field) } -func (_LatestValueHolder *LatestValueHolderSession) TriggerEventWithDynamicTopic(field string) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerEventWithDynamicTopic(&_LatestValueHolder.TransactOpts, field) +func (_ChainReaderTester *ChainReaderTesterSession) TriggerEventWithDynamicTopic(field string) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEventWithDynamicTopic(&_ChainReaderTester.TransactOpts, field) } -func (_LatestValueHolder *LatestValueHolderTransactorSession) TriggerEventWithDynamicTopic(field string) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerEventWithDynamicTopic(&_LatestValueHolder.TransactOpts, field) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEventWithDynamicTopic(field string) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEventWithDynamicTopic(&_ChainReaderTester.TransactOpts, field) } -func (_LatestValueHolder *LatestValueHolderTransactor) TriggerWithFourTopics(opts *bind.TransactOpts, field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { - return _LatestValueHolder.contract.Transact(opts, "triggerWithFourTopics", field1, field2, field3) +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerWithFourTopics(opts *bind.TransactOpts, field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerWithFourTopics", field1, field2, field3) } -func (_LatestValueHolder *LatestValueHolderSession) TriggerWithFourTopics(field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerWithFourTopics(&_LatestValueHolder.TransactOpts, field1, field2, field3) +func (_ChainReaderTester *ChainReaderTesterSession) TriggerWithFourTopics(field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerWithFourTopics(&_ChainReaderTester.TransactOpts, field1, field2, field3) } -func (_LatestValueHolder *LatestValueHolderTransactorSession) TriggerWithFourTopics(field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { - return _LatestValueHolder.Contract.TriggerWithFourTopics(&_LatestValueHolder.TransactOpts, field1, field2, field3) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerWithFourTopics(field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerWithFourTopics(&_ChainReaderTester.TransactOpts, field1, field2, field3) } -type LatestValueHolderTriggeredIterator struct { - Event *LatestValueHolderTriggered +type ChainReaderTesterTriggeredIterator struct { + Event *ChainReaderTesterTriggered contract *bind.BoundContract event string @@ -362,7 +362,7 @@ type LatestValueHolderTriggeredIterator struct { fail error } -func (it *LatestValueHolderTriggeredIterator) Next() bool { +func (it *ChainReaderTesterTriggeredIterator) Next() bool { if it.fail != nil { return false @@ -371,7 +371,7 @@ func (it *LatestValueHolderTriggeredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggered) + it.Event = new(ChainReaderTesterTriggered) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -386,7 +386,7 @@ func (it *LatestValueHolderTriggeredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggered) + it.Event = new(ChainReaderTesterTriggered) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -401,16 +401,16 @@ func (it *LatestValueHolderTriggeredIterator) Next() bool { } } -func (it *LatestValueHolderTriggeredIterator) Error() error { +func (it *ChainReaderTesterTriggeredIterator) Error() error { return it.fail } -func (it *LatestValueHolderTriggeredIterator) Close() error { +func (it *ChainReaderTesterTriggeredIterator) Close() error { it.sub.Unsubscribe() return nil } -type LatestValueHolderTriggered struct { +type ChainReaderTesterTriggered struct { Field int32 DifferentField string OracleId uint8 @@ -422,28 +422,28 @@ type LatestValueHolderTriggered struct { Raw types.Log } -func (_LatestValueHolder *LatestValueHolderFilterer) FilterTriggered(opts *bind.FilterOpts, field []int32) (*LatestValueHolderTriggeredIterator, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) FilterTriggered(opts *bind.FilterOpts, field []int32) (*ChainReaderTesterTriggeredIterator, error) { var fieldRule []interface{} for _, fieldItem := range field { fieldRule = append(fieldRule, fieldItem) } - logs, sub, err := _LatestValueHolder.contract.FilterLogs(opts, "Triggered", fieldRule) + logs, sub, err := _ChainReaderTester.contract.FilterLogs(opts, "Triggered", fieldRule) if err != nil { return nil, err } - return &LatestValueHolderTriggeredIterator{contract: _LatestValueHolder.contract, event: "Triggered", logs: logs, sub: sub}, nil + return &ChainReaderTesterTriggeredIterator{contract: _ChainReaderTester.contract, event: "Triggered", logs: logs, sub: sub}, nil } -func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggered(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggered, field []int32) (event.Subscription, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) WatchTriggered(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggered, field []int32) (event.Subscription, error) { var fieldRule []interface{} for _, fieldItem := range field { fieldRule = append(fieldRule, fieldItem) } - logs, sub, err := _LatestValueHolder.contract.WatchLogs(opts, "Triggered", fieldRule) + logs, sub, err := _ChainReaderTester.contract.WatchLogs(opts, "Triggered", fieldRule) if err != nil { return nil, err } @@ -453,8 +453,8 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggered(opts *bind.W select { case log := <-logs: - event := new(LatestValueHolderTriggered) - if err := _LatestValueHolder.contract.UnpackLog(event, "Triggered", log); err != nil { + event := new(ChainReaderTesterTriggered) + if err := _ChainReaderTester.contract.UnpackLog(event, "Triggered", log); err != nil { return err } event.Raw = log @@ -475,17 +475,17 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggered(opts *bind.W }), nil } -func (_LatestValueHolder *LatestValueHolderFilterer) ParseTriggered(log types.Log) (*LatestValueHolderTriggered, error) { - event := new(LatestValueHolderTriggered) - if err := _LatestValueHolder.contract.UnpackLog(event, "Triggered", log); err != nil { +func (_ChainReaderTester *ChainReaderTesterFilterer) ParseTriggered(log types.Log) (*ChainReaderTesterTriggered, error) { + event := new(ChainReaderTesterTriggered) + if err := _ChainReaderTester.contract.UnpackLog(event, "Triggered", log); err != nil { return nil, err } event.Raw = log return event, nil } -type LatestValueHolderTriggeredEventWithDynamicTopicIterator struct { - Event *LatestValueHolderTriggeredEventWithDynamicTopic +type ChainReaderTesterTriggeredEventWithDynamicTopicIterator struct { + Event *ChainReaderTesterTriggeredEventWithDynamicTopic contract *bind.BoundContract event string @@ -496,7 +496,7 @@ type LatestValueHolderTriggeredEventWithDynamicTopicIterator struct { fail error } -func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Next() bool { +func (it *ChainReaderTesterTriggeredEventWithDynamicTopicIterator) Next() bool { if it.fail != nil { return false @@ -505,7 +505,7 @@ func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggeredEventWithDynamicTopic) + it.Event = new(ChainReaderTesterTriggeredEventWithDynamicTopic) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -520,7 +520,7 @@ func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggeredEventWithDynamicTopic) + it.Event = new(ChainReaderTesterTriggeredEventWithDynamicTopic) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -535,43 +535,43 @@ func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Next() bool { } } -func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Error() error { +func (it *ChainReaderTesterTriggeredEventWithDynamicTopicIterator) Error() error { return it.fail } -func (it *LatestValueHolderTriggeredEventWithDynamicTopicIterator) Close() error { +func (it *ChainReaderTesterTriggeredEventWithDynamicTopicIterator) Close() error { it.sub.Unsubscribe() return nil } -type LatestValueHolderTriggeredEventWithDynamicTopic struct { +type ChainReaderTesterTriggeredEventWithDynamicTopic struct { FieldHash common.Hash Field string Raw types.Log } -func (_LatestValueHolder *LatestValueHolderFilterer) FilterTriggeredEventWithDynamicTopic(opts *bind.FilterOpts, fieldHash []string) (*LatestValueHolderTriggeredEventWithDynamicTopicIterator, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) FilterTriggeredEventWithDynamicTopic(opts *bind.FilterOpts, fieldHash []string) (*ChainReaderTesterTriggeredEventWithDynamicTopicIterator, error) { var fieldHashRule []interface{} for _, fieldHashItem := range fieldHash { fieldHashRule = append(fieldHashRule, fieldHashItem) } - logs, sub, err := _LatestValueHolder.contract.FilterLogs(opts, "TriggeredEventWithDynamicTopic", fieldHashRule) + logs, sub, err := _ChainReaderTester.contract.FilterLogs(opts, "TriggeredEventWithDynamicTopic", fieldHashRule) if err != nil { return nil, err } - return &LatestValueHolderTriggeredEventWithDynamicTopicIterator{contract: _LatestValueHolder.contract, event: "TriggeredEventWithDynamicTopic", logs: logs, sub: sub}, nil + return &ChainReaderTesterTriggeredEventWithDynamicTopicIterator{contract: _ChainReaderTester.contract, event: "TriggeredEventWithDynamicTopic", logs: logs, sub: sub}, nil } -func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredEventWithDynamicTopic(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggeredEventWithDynamicTopic, fieldHash []string) (event.Subscription, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) WatchTriggeredEventWithDynamicTopic(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggeredEventWithDynamicTopic, fieldHash []string) (event.Subscription, error) { var fieldHashRule []interface{} for _, fieldHashItem := range fieldHash { fieldHashRule = append(fieldHashRule, fieldHashItem) } - logs, sub, err := _LatestValueHolder.contract.WatchLogs(opts, "TriggeredEventWithDynamicTopic", fieldHashRule) + logs, sub, err := _ChainReaderTester.contract.WatchLogs(opts, "TriggeredEventWithDynamicTopic", fieldHashRule) if err != nil { return nil, err } @@ -581,8 +581,8 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredEventWithDyna select { case log := <-logs: - event := new(LatestValueHolderTriggeredEventWithDynamicTopic) - if err := _LatestValueHolder.contract.UnpackLog(event, "TriggeredEventWithDynamicTopic", log); err != nil { + event := new(ChainReaderTesterTriggeredEventWithDynamicTopic) + if err := _ChainReaderTester.contract.UnpackLog(event, "TriggeredEventWithDynamicTopic", log); err != nil { return err } event.Raw = log @@ -603,17 +603,17 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredEventWithDyna }), nil } -func (_LatestValueHolder *LatestValueHolderFilterer) ParseTriggeredEventWithDynamicTopic(log types.Log) (*LatestValueHolderTriggeredEventWithDynamicTopic, error) { - event := new(LatestValueHolderTriggeredEventWithDynamicTopic) - if err := _LatestValueHolder.contract.UnpackLog(event, "TriggeredEventWithDynamicTopic", log); err != nil { +func (_ChainReaderTester *ChainReaderTesterFilterer) ParseTriggeredEventWithDynamicTopic(log types.Log) (*ChainReaderTesterTriggeredEventWithDynamicTopic, error) { + event := new(ChainReaderTesterTriggeredEventWithDynamicTopic) + if err := _ChainReaderTester.contract.UnpackLog(event, "TriggeredEventWithDynamicTopic", log); err != nil { return nil, err } event.Raw = log return event, nil } -type LatestValueHolderTriggeredWithFourTopicsIterator struct { - Event *LatestValueHolderTriggeredWithFourTopics +type ChainReaderTesterTriggeredWithFourTopicsIterator struct { + Event *ChainReaderTesterTriggeredWithFourTopics contract *bind.BoundContract event string @@ -624,7 +624,7 @@ type LatestValueHolderTriggeredWithFourTopicsIterator struct { fail error } -func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Next() bool { +func (it *ChainReaderTesterTriggeredWithFourTopicsIterator) Next() bool { if it.fail != nil { return false @@ -633,7 +633,7 @@ func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggeredWithFourTopics) + it.Event = new(ChainReaderTesterTriggeredWithFourTopics) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -648,7 +648,7 @@ func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(LatestValueHolderTriggeredWithFourTopics) + it.Event = new(ChainReaderTesterTriggeredWithFourTopics) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -663,23 +663,23 @@ func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Next() bool { } } -func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Error() error { +func (it *ChainReaderTesterTriggeredWithFourTopicsIterator) Error() error { return it.fail } -func (it *LatestValueHolderTriggeredWithFourTopicsIterator) Close() error { +func (it *ChainReaderTesterTriggeredWithFourTopicsIterator) Close() error { it.sub.Unsubscribe() return nil } -type LatestValueHolderTriggeredWithFourTopics struct { +type ChainReaderTesterTriggeredWithFourTopics struct { Field1 int32 Field2 int32 Field3 int32 Raw types.Log } -func (_LatestValueHolder *LatestValueHolderFilterer) FilterTriggeredWithFourTopics(opts *bind.FilterOpts, field1 []int32, field2 []int32, field3 []int32) (*LatestValueHolderTriggeredWithFourTopicsIterator, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) FilterTriggeredWithFourTopics(opts *bind.FilterOpts, field1 []int32, field2 []int32, field3 []int32) (*ChainReaderTesterTriggeredWithFourTopicsIterator, error) { var field1Rule []interface{} for _, field1Item := range field1 { @@ -694,14 +694,14 @@ func (_LatestValueHolder *LatestValueHolderFilterer) FilterTriggeredWithFourTopi field3Rule = append(field3Rule, field3Item) } - logs, sub, err := _LatestValueHolder.contract.FilterLogs(opts, "TriggeredWithFourTopics", field1Rule, field2Rule, field3Rule) + logs, sub, err := _ChainReaderTester.contract.FilterLogs(opts, "TriggeredWithFourTopics", field1Rule, field2Rule, field3Rule) if err != nil { return nil, err } - return &LatestValueHolderTriggeredWithFourTopicsIterator{contract: _LatestValueHolder.contract, event: "TriggeredWithFourTopics", logs: logs, sub: sub}, nil + return &ChainReaderTesterTriggeredWithFourTopicsIterator{contract: _ChainReaderTester.contract, event: "TriggeredWithFourTopics", logs: logs, sub: sub}, nil } -func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredWithFourTopics(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggeredWithFourTopics, field1 []int32, field2 []int32, field3 []int32) (event.Subscription, error) { +func (_ChainReaderTester *ChainReaderTesterFilterer) WatchTriggeredWithFourTopics(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggeredWithFourTopics, field1 []int32, field2 []int32, field3 []int32) (event.Subscription, error) { var field1Rule []interface{} for _, field1Item := range field1 { @@ -716,7 +716,7 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredWithFourTopic field3Rule = append(field3Rule, field3Item) } - logs, sub, err := _LatestValueHolder.contract.WatchLogs(opts, "TriggeredWithFourTopics", field1Rule, field2Rule, field3Rule) + logs, sub, err := _ChainReaderTester.contract.WatchLogs(opts, "TriggeredWithFourTopics", field1Rule, field2Rule, field3Rule) if err != nil { return nil, err } @@ -726,8 +726,8 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredWithFourTopic select { case log := <-logs: - event := new(LatestValueHolderTriggeredWithFourTopics) - if err := _LatestValueHolder.contract.UnpackLog(event, "TriggeredWithFourTopics", log); err != nil { + event := new(ChainReaderTesterTriggeredWithFourTopics) + if err := _ChainReaderTester.contract.UnpackLog(event, "TriggeredWithFourTopics", log); err != nil { return err } event.Raw = log @@ -748,46 +748,46 @@ func (_LatestValueHolder *LatestValueHolderFilterer) WatchTriggeredWithFourTopic }), nil } -func (_LatestValueHolder *LatestValueHolderFilterer) ParseTriggeredWithFourTopics(log types.Log) (*LatestValueHolderTriggeredWithFourTopics, error) { - event := new(LatestValueHolderTriggeredWithFourTopics) - if err := _LatestValueHolder.contract.UnpackLog(event, "TriggeredWithFourTopics", log); err != nil { +func (_ChainReaderTester *ChainReaderTesterFilterer) ParseTriggeredWithFourTopics(log types.Log) (*ChainReaderTesterTriggeredWithFourTopics, error) { + event := new(ChainReaderTesterTriggeredWithFourTopics) + if err := _ChainReaderTester.contract.UnpackLog(event, "TriggeredWithFourTopics", log); err != nil { return nil, err } event.Raw = log return event, nil } -func (_LatestValueHolder *LatestValueHolder) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_ChainReaderTester *ChainReaderTester) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _LatestValueHolder.abi.Events["Triggered"].ID: - return _LatestValueHolder.ParseTriggered(log) - case _LatestValueHolder.abi.Events["TriggeredEventWithDynamicTopic"].ID: - return _LatestValueHolder.ParseTriggeredEventWithDynamicTopic(log) - case _LatestValueHolder.abi.Events["TriggeredWithFourTopics"].ID: - return _LatestValueHolder.ParseTriggeredWithFourTopics(log) + case _ChainReaderTester.abi.Events["Triggered"].ID: + return _ChainReaderTester.ParseTriggered(log) + case _ChainReaderTester.abi.Events["TriggeredEventWithDynamicTopic"].ID: + return _ChainReaderTester.ParseTriggeredEventWithDynamicTopic(log) + case _ChainReaderTester.abi.Events["TriggeredWithFourTopics"].ID: + return _ChainReaderTester.ParseTriggeredWithFourTopics(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (LatestValueHolderTriggered) Topic() common.Hash { +func (ChainReaderTesterTriggered) Topic() common.Hash { return common.HexToHash("0x7188419dcd8b51877b71766f075f3626586c0ff190e7d056aa65ce9acb649a3d") } -func (LatestValueHolderTriggeredEventWithDynamicTopic) Topic() common.Hash { +func (ChainReaderTesterTriggeredEventWithDynamicTopic) Topic() common.Hash { return common.HexToHash("0x3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c67") } -func (LatestValueHolderTriggeredWithFourTopics) Topic() common.Hash { +func (ChainReaderTesterTriggeredWithFourTopics) Topic() common.Hash { return common.HexToHash("0x91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac5") } -func (_LatestValueHolder *LatestValueHolder) Address() common.Address { - return _LatestValueHolder.address +func (_ChainReaderTester *ChainReaderTester) Address() common.Address { + return _ChainReaderTester.address } -type LatestValueHolderInterface interface { +type ChainReaderTesterInterface interface { GetDifferentPrimitiveValue(opts *bind.CallOpts) (uint64, error) GetElementAtIndex(opts *bind.CallOpts, i *big.Int) (TestStruct, error) @@ -806,23 +806,23 @@ type LatestValueHolderInterface interface { TriggerWithFourTopics(opts *bind.TransactOpts, field1 int32, field2 int32, field3 int32) (*types.Transaction, error) - FilterTriggered(opts *bind.FilterOpts, field []int32) (*LatestValueHolderTriggeredIterator, error) + FilterTriggered(opts *bind.FilterOpts, field []int32) (*ChainReaderTesterTriggeredIterator, error) - WatchTriggered(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggered, field []int32) (event.Subscription, error) + WatchTriggered(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggered, field []int32) (event.Subscription, error) - ParseTriggered(log types.Log) (*LatestValueHolderTriggered, error) + ParseTriggered(log types.Log) (*ChainReaderTesterTriggered, error) - FilterTriggeredEventWithDynamicTopic(opts *bind.FilterOpts, fieldHash []string) (*LatestValueHolderTriggeredEventWithDynamicTopicIterator, error) + FilterTriggeredEventWithDynamicTopic(opts *bind.FilterOpts, fieldHash []string) (*ChainReaderTesterTriggeredEventWithDynamicTopicIterator, error) - WatchTriggeredEventWithDynamicTopic(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggeredEventWithDynamicTopic, fieldHash []string) (event.Subscription, error) + WatchTriggeredEventWithDynamicTopic(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggeredEventWithDynamicTopic, fieldHash []string) (event.Subscription, error) - ParseTriggeredEventWithDynamicTopic(log types.Log) (*LatestValueHolderTriggeredEventWithDynamicTopic, error) + ParseTriggeredEventWithDynamicTopic(log types.Log) (*ChainReaderTesterTriggeredEventWithDynamicTopic, error) - FilterTriggeredWithFourTopics(opts *bind.FilterOpts, field1 []int32, field2 []int32, field3 []int32) (*LatestValueHolderTriggeredWithFourTopicsIterator, error) + FilterTriggeredWithFourTopics(opts *bind.FilterOpts, field1 []int32, field2 []int32, field3 []int32) (*ChainReaderTesterTriggeredWithFourTopicsIterator, error) - WatchTriggeredWithFourTopics(opts *bind.WatchOpts, sink chan<- *LatestValueHolderTriggeredWithFourTopics, field1 []int32, field2 []int32, field3 []int32) (event.Subscription, error) + WatchTriggeredWithFourTopics(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggeredWithFourTopics, field1 []int32, field2 []int32, field3 []int32) (event.Subscription, error) - ParseTriggeredWithFourTopics(log types.Log) (*LatestValueHolderTriggeredWithFourTopics, error) + ParseTriggeredWithFourTopics(log types.Log) (*ChainReaderTesterTriggeredWithFourTopics, error) ParseLog(log types.Log) (generated.AbigenLog, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 37a52ccd949..8e4200d36b9 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ batch_vrf_coordinator_v2: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/Batc batch_vrf_coordinator_v2plus: ../../contracts/solc/v0.8.19/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.19/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.bin ace5851ac0b419ee93f3c716ee13e77c530531248119f3970657f84dfcd73c6e blockhash_store: ../../contracts/solc/v0.8.19/BlockhashStore/BlockhashStore.abi ../../contracts/solc/v0.8.19/BlockhashStore/BlockhashStore.bin 31b118f9577240c8834c35f8b5a1440e82a6ca8aea702970de2601824b6ab0e1 chain_module_base: ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.abi ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.bin 39dfce79330e921e5c169051b11c6e5ea15cd4db5a7b09c06aabbe9658148915 -chain_reader_example: ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.abi ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.bin de88c7e68de36b96aa2bec844bdc96fcd7c9017b38e25062b3b9f9cec42c814f +chain_reader_tester: ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin de88c7e68de36b96aa2bec844bdc96fcd7c9017b38e25062b3b9f9cec42c814f chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin 5f10664e31abc768f4a37901cae7a3bef90146180f97303e5a1bde5a08d84595 cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7 cron_upkeep_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.abi - 362fcfcf30a6ab3acff83095ea4b2b9056dd5e9dcb94bc5411aae58995d22709 diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index c5a55b18a05..5803e67c17b 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -144,7 +144,7 @@ package gethwrappers // Log tester // ChainReader test contract -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.abi ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.bin LatestValueHolder chain_reader_example +//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin ChainReaderTester chain_reader_tester // Chainlink Functions //go:generate go generate ./functions diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index 5a6466a8b15..082318518a5 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -22,6 +22,8 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink-common/pkg/services" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" @@ -344,11 +346,11 @@ func (r *EvmRegistry) refreshLogTriggerUpkeepsBatch(logTriggerIDs []*big.Int) er logTriggerHashes = append(logTriggerHashes, common.BigToHash(id)) } - unpausedLogs, err := r.poller.IndexedLogs(r.ctx, ac.IAutomationV21PlusCommonUpkeepUnpaused{}.Topic(), r.addr, 1, logTriggerHashes, logpoller.Confirmations(r.finalityDepth)) + unpausedLogs, err := r.poller.IndexedLogs(r.ctx, ac.IAutomationV21PlusCommonUpkeepUnpaused{}.Topic(), r.addr, 1, logTriggerHashes, evmtypes.Confirmations(r.finalityDepth)) if err != nil { return err } - configSetLogs, err := r.poller.IndexedLogs(r.ctx, ac.IAutomationV21PlusCommonUpkeepTriggerConfigSet{}.Topic(), r.addr, 1, logTriggerHashes, logpoller.Confirmations(r.finalityDepth)) + configSetLogs, err := r.poller.IndexedLogs(r.ctx, ac.IAutomationV21PlusCommonUpkeepTriggerConfigSet{}.Topic(), r.addr, 1, logTriggerHashes, evmtypes.Confirmations(r.finalityDepth)) if err != nil { return err } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go index e74ad4821a6..f1b9cc66ae4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go @@ -26,6 +26,7 @@ import ( gasMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -216,14 +217,14 @@ func TestRegistry_VerifyCheckBlock(t *testing.T) { type mockLogPoller struct { logpoller.LogPoller GetBlocksRangeFn func(ctx context.Context, numbers []uint64) ([]logpoller.LogPollerBlock, error) - IndexedLogsFn func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) + IndexedLogsFn func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) } func (p *mockLogPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]logpoller.LogPollerBlock, error) { return p.GetBlocksRangeFn(ctx, numbers) } -func (p *mockLogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { +func (p *mockLogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return p.IndexedLogsFn(ctx, eventSig, address, topicIndex, topicValues, confs) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go index 4dcb72fde86..34b3f822dbf 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go @@ -16,6 +16,7 @@ import ( types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" "github.com/smartcontractkit/chainlink-common/pkg/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -264,7 +265,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { if eventSig == (autov2common.IAutomationV21PlusCommonUpkeepUnpaused{}.Topic()) { return nil, errors.New("indexed logs boom") } @@ -289,7 +290,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { if eventSig == (autov2common.IAutomationV21PlusCommonUpkeepTriggerConfigSet{}.Topic()) { return nil, errors.New("indexed logs boom") } @@ -314,7 +315,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return []logpoller.Log{ {}, }, nil @@ -346,7 +347,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return []logpoller.Log{ { BlockNumber: 1, @@ -400,7 +401,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return []logpoller.Log{ { BlockNumber: 2, @@ -452,7 +453,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return []logpoller.Log{ { BlockNumber: 2, @@ -506,7 +507,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { }, }, poller: &mockLogPoller{ - IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { + IndexedLogsFn: func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs evmtypes.Confirmations) ([]logpoller.Log, error) { return []logpoller.Log{ { BlockNumber: 2, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go index 93b0c155870..d11970864ad 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" @@ -79,7 +80,7 @@ func (s *performedEventsScanner) ScanWorkIDs(ctx context.Context, workID ...stri } batch := ids[i:end] - batchLogs, err := s.poller.IndexedLogs(ctx, ac.IAutomationV21PlusCommonDedupKeyAdded{}.Topic(), s.registryAddress, 1, batch, logpoller.Confirmations(s.finalityDepth)) + batchLogs, err := s.poller.IndexedLogs(ctx, ac.IAutomationV21PlusCommonDedupKeyAdded{}.Topic(), s.registryAddress, 1, batch, evmtypes.Confirmations(s.finalityDepth)) if err != nil { return nil, fmt.Errorf("error fetching logs: %w", err) } diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go index 1cb2d613d31..f77b99b3568 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go @@ -909,7 +909,7 @@ func (c *coordinator) DKGVRFCommittees(ctx context.Context) (dkgCommittee, vrfCo ctx, c.configSetTopic, c.beaconAddress, - logpoller.Confirmations(c.finalityDepth), + evmtypes.Confirmations(c.finalityDepth), ) if err != nil { err = errors.Wrap(err, "latest vrf ConfigSet by sig with confs") @@ -920,7 +920,7 @@ func (c *coordinator) DKGVRFCommittees(ctx context.Context) (dkgCommittee, vrfCo ctx, c.configSetTopic, c.dkgAddress, - logpoller.Confirmations(c.finalityDepth), + evmtypes.Confirmations(c.finalityDepth), ) if err != nil { err = errors.Wrap(err, "latest dkg ConfigSet by sig with confs") diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go index e5913b0a844..d0f89ae4ca9 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-vrf/dkg" "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" @@ -85,11 +86,11 @@ func TestCoordinator_DKGVRFCommittees(t *testing.T) { coordinatorAddress := newAddress(t) beaconAddress := newAddress(t) dkgAddress := newAddress(t) - lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, logpoller.Confirmations(10)). + lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, evmtypes.Confirmations(10)). Return(&logpoller.Log{ Data: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000a6fca200010576e704b4a519484d6239ef17f1f5b4a82e330b0daf827ed4dc2789971b0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000a8cbea12a06869d3ec432ab9682dab6c761d591000000000000000000000000f4f9db7bb1d16b7cdfb18ec68994c26964f5985300000000000000000000000022fb3f90c539457f00d8484438869135e604a65500000000000000000000000033cbcedccb11c9773ad78e214ba342e979255ab30000000000000000000000006ffaa96256fbc1012325cca88c79f725c33eed80000000000000000000000000000000000000000000000000000000000000000500000000000000000000000074103cf8b436465870b26aa9fa2f62ad62b22e3500000000000000000000000038a6cb196f805cc3041f6645a5a6cec27b64430d00000000000000000000000047d7095cfebf8285bdaa421bc8268d0db87d933c000000000000000000000000a8842be973800ff61d80d2d53fa62c3a685380eb0000000000000000000000003750e31321aee8c024751877070e8d5f704ce98700000000000000000000000000000000000000000000000000000000000000206f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c715fbf000000000000000000000000000000000000000000000000000000000000004220880d88ee16f1080c8afa0251880c8afa025208090dfc04a288090dfc04a30033a05010101010142206c5ca6f74b532222ac927dd3de235d46a943e372c0563393a33b01dcfd3f371c4220855114d25c2ef5e85fffe4f20a365672d8f2dba3b2ec82333f494168a2039c0442200266e835634db00977cbc1caa4db10e1676c1a4c0fcbc6ba7f09300f0d1831824220980cd91f7a73f20f4b0d51d00cd4e00373dc2beafbb299ca3c609757ab98c8304220eb6d36e2af8922085ff510bbe1eb8932a0e3295ca9f047fef25d90e69c52948f4a34313244334b6f6f574463364b7232644542684b59326b336e685057694676544565325331703978544532544b74344d7572716f684a34313244334b6f6f574b436e4367724b637743324a3577576a626e355435335068646b6b6f57454e534a39546537544b7836366f4a4a34313244334b6f6f575239616f675948786b357a38636b624c4c56346e426f7a777a747871664a7050586671336d4a7232796452474a34313244334b6f6f5744695444635565675637776b313133473366476a69616259756f54436f3157726f6f53656741343263556f544a34313244334b6f6f574e64687072586b5472665370354d5071736270467a70364167394a53787358694341434442676454424c656652820300050e416c74424e2d3132382047e282810e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c216a812d7616e47f0bd38fa4863f48fbcda6a38af4c58d2233dfa7cf79620947042d09f923e0a2f7a2270391e8b058d8bdb8f79fe082b7b627f025651c7290382fdff97c3181d15d162c146ce87ff752499d2acc2b26011439a12e29571a6f1e1defb1751c3be4258c493984fd9f0f6b4a26c539870b5f15bfed3d8ffac92499eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b127a112970e1adf615f823b2b2180754c2f0ee01f1b389e56df55ca09702cd0401b66ff71779d2dd67222503a85ab921b28c329cc1832800b192d0b0247c0776e1b9653dc00df48daa6364287c84c0382f5165e7269fef06d10bc67c1bba252305d1af0dc7bb0fe92558eb4c5f38c23163dee1cfb34a72020669dbdfe337c16f3307472616e736c61746f722066726f6d20416c74424e2d3132382047e2828120746f20416c74424e2d3132382047e282825880ade2046080c8afa0256880c8afa0257080ade204788094ebdc0382019e010a205034214e0bd4373f38e162cf9fc9133e2f3b71441faa4c3d1ac01c1877f1cd2712200e03e975b996f911abba2b79d2596c2150bc94510963c40a1137a03df6edacdb1a107dee1cdb894163813bb3da604c9c133c1a10bb33302eeafbd55d352e35dcc5d2b3311a10d2c658b6b93d74a02d467849b6fe75251a10fea5308cc1fea69e7246eafe7ca8a3a51a1048efe1ad873b6f025ac0243bdef715f8000000000000000000000000000000000000000000000000000000000000"), }, nil) - lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, dkgAddress, logpoller.Confirmations(10)). + lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, dkgAddress, evmtypes.Confirmations(10)). Return(&logpoller.Log{ Data: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000a6fca200010576e704b4a519484d6239ef17f1f5b4a82e330b0daf827ed4dc2789971b0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000a8cbea12a06869d3ec432ab9682dab6c761d591000000000000000000000000f4f9db7bb1d16b7cdfb18ec68994c26964f5985300000000000000000000000022fb3f90c539457f00d8484438869135e604a65500000000000000000000000033cbcedccb11c9773ad78e214ba342e979255ab30000000000000000000000006ffaa96256fbc1012325cca88c79f725c33eed80000000000000000000000000000000000000000000000000000000000000000500000000000000000000000074103cf8b436465870b26aa9fa2f62ad62b22e3500000000000000000000000038a6cb196f805cc3041f6645a5a6cec27b64430d00000000000000000000000047d7095cfebf8285bdaa421bc8268d0db87d933c000000000000000000000000a8842be973800ff61d80d2d53fa62c3a685380eb0000000000000000000000003750e31321aee8c024751877070e8d5f704ce98700000000000000000000000000000000000000000000000000000000000000206f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c715fbf000000000000000000000000000000000000000000000000000000000000004220880d88ee16f1080c8afa0251880c8afa025208090dfc04a288090dfc04a30033a05010101010142206c5ca6f74b532222ac927dd3de235d46a943e372c0563393a33b01dcfd3f371c4220855114d25c2ef5e85fffe4f20a365672d8f2dba3b2ec82333f494168a2039c0442200266e835634db00977cbc1caa4db10e1676c1a4c0fcbc6ba7f09300f0d1831824220980cd91f7a73f20f4b0d51d00cd4e00373dc2beafbb299ca3c609757ab98c8304220eb6d36e2af8922085ff510bbe1eb8932a0e3295ca9f047fef25d90e69c52948f4a34313244334b6f6f574463364b7232644542684b59326b336e685057694676544565325331703978544532544b74344d7572716f684a34313244334b6f6f574b436e4367724b637743324a3577576a626e355435335068646b6b6f57454e534a39546537544b7836366f4a4a34313244334b6f6f575239616f675948786b357a38636b624c4c56346e426f7a777a747871664a7050586671336d4a7232796452474a34313244334b6f6f5744695444635565675637776b313133473366476a69616259756f54436f3157726f6f53656741343263556f544a34313244334b6f6f574e64687072586b5472665370354d5071736270467a70364167394a53787358694341434442676454424c656652820300050e416c74424e2d3132382047e282810e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c216a812d7616e47f0bd38fa4863f48fbcda6a38af4c58d2233dfa7cf79620947042d09f923e0a2f7a2270391e8b058d8bdb8f79fe082b7b627f025651c7290382fdff97c3181d15d162c146ce87ff752499d2acc2b26011439a12e29571a6f1e1defb1751c3be4258c493984fd9f0f6b4a26c539870b5f15bfed3d8ffac92499eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b127a112970e1adf615f823b2b2180754c2f0ee01f1b389e56df55ca09702cd0401b66ff71779d2dd67222503a85ab921b28c329cc1832800b192d0b0247c0776e1b9653dc00df48daa6364287c84c0382f5165e7269fef06d10bc67c1bba252305d1af0dc7bb0fe92558eb4c5f38c23163dee1cfb34a72020669dbdfe337c16f3307472616e736c61746f722066726f6d20416c74424e2d3132382047e2828120746f20416c74424e2d3132382047e282825880ade2046080c8afa0256880c8afa0257080ade204788094ebdc0382019e010a205034214e0bd4373f38e162cf9fc9133e2f3b71441faa4c3d1ac01c1877f1cd2712200e03e975b996f911abba2b79d2596c2150bc94510963c40a1137a03df6edacdb1a107dee1cdb894163813bb3da604c9c133c1a10bb33302eeafbd55d352e35dcc5d2b3311a10d2c658b6b93d74a02d467849b6fe75251a10fea5308cc1fea69e7246eafe7ca8a3a51a1048efe1ad873b6f025ac0243bdef715f8000000000000000000000000000000000000000000000000000000000000"), }, nil) @@ -134,7 +135,7 @@ func TestCoordinator_DKGVRFCommittees(t *testing.T) { tp := newTopics() beaconAddress := newAddress(t) - lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, logpoller.Confirmations(10)). + lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, evmtypes.Confirmations(10)). Return(nil, errors.New("rpc error")) c := &coordinator{ @@ -156,11 +157,11 @@ func TestCoordinator_DKGVRFCommittees(t *testing.T) { beaconAddress := newAddress(t) coordinatorAddress := newAddress(t) dkgAddress := newAddress(t) - lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, logpoller.Confirmations(10)). + lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, beaconAddress, evmtypes.Confirmations(10)). Return(&logpoller.Log{ Data: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000a6fca200010576e704b4a519484d6239ef17f1f5b4a82e330b0daf827ed4dc2789971b0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000a8cbea12a06869d3ec432ab9682dab6c761d591000000000000000000000000f4f9db7bb1d16b7cdfb18ec68994c26964f5985300000000000000000000000022fb3f90c539457f00d8484438869135e604a65500000000000000000000000033cbcedccb11c9773ad78e214ba342e979255ab30000000000000000000000006ffaa96256fbc1012325cca88c79f725c33eed80000000000000000000000000000000000000000000000000000000000000000500000000000000000000000074103cf8b436465870b26aa9fa2f62ad62b22e3500000000000000000000000038a6cb196f805cc3041f6645a5a6cec27b64430d00000000000000000000000047d7095cfebf8285bdaa421bc8268d0db87d933c000000000000000000000000a8842be973800ff61d80d2d53fa62c3a685380eb0000000000000000000000003750e31321aee8c024751877070e8d5f704ce98700000000000000000000000000000000000000000000000000000000000000206f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c715fbf000000000000000000000000000000000000000000000000000000000000004220880d88ee16f1080c8afa0251880c8afa025208090dfc04a288090dfc04a30033a05010101010142206c5ca6f74b532222ac927dd3de235d46a943e372c0563393a33b01dcfd3f371c4220855114d25c2ef5e85fffe4f20a365672d8f2dba3b2ec82333f494168a2039c0442200266e835634db00977cbc1caa4db10e1676c1a4c0fcbc6ba7f09300f0d1831824220980cd91f7a73f20f4b0d51d00cd4e00373dc2beafbb299ca3c609757ab98c8304220eb6d36e2af8922085ff510bbe1eb8932a0e3295ca9f047fef25d90e69c52948f4a34313244334b6f6f574463364b7232644542684b59326b336e685057694676544565325331703978544532544b74344d7572716f684a34313244334b6f6f574b436e4367724b637743324a3577576a626e355435335068646b6b6f57454e534a39546537544b7836366f4a4a34313244334b6f6f575239616f675948786b357a38636b624c4c56346e426f7a777a747871664a7050586671336d4a7232796452474a34313244334b6f6f5744695444635565675637776b313133473366476a69616259756f54436f3157726f6f53656741343263556f544a34313244334b6f6f574e64687072586b5472665370354d5071736270467a70364167394a53787358694341434442676454424c656652820300050e416c74424e2d3132382047e282810e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c216a812d7616e47f0bd38fa4863f48fbcda6a38af4c58d2233dfa7cf79620947042d09f923e0a2f7a2270391e8b058d8bdb8f79fe082b7b627f025651c7290382fdff97c3181d15d162c146ce87ff752499d2acc2b26011439a12e29571a6f1e1defb1751c3be4258c493984fd9f0f6b4a26c539870b5f15bfed3d8ffac92499eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b127a112970e1adf615f823b2b2180754c2f0ee01f1b389e56df55ca09702cd0401b66ff71779d2dd67222503a85ab921b28c329cc1832800b192d0b0247c0776e1b9653dc00df48daa6364287c84c0382f5165e7269fef06d10bc67c1bba252305d1af0dc7bb0fe92558eb4c5f38c23163dee1cfb34a72020669dbdfe337c16f3307472616e736c61746f722066726f6d20416c74424e2d3132382047e2828120746f20416c74424e2d3132382047e282825880ade2046080c8afa0256880c8afa0257080ade204788094ebdc0382019e010a205034214e0bd4373f38e162cf9fc9133e2f3b71441faa4c3d1ac01c1877f1cd2712200e03e975b996f911abba2b79d2596c2150bc94510963c40a1137a03df6edacdb1a107dee1cdb894163813bb3da604c9c133c1a10bb33302eeafbd55d352e35dcc5d2b3311a10d2c658b6b93d74a02d467849b6fe75251a10fea5308cc1fea69e7246eafe7ca8a3a51a1048efe1ad873b6f025ac0243bdef715f8000000000000000000000000000000000000000000000000000000000000"), }, nil) - lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, dkgAddress, logpoller.Confirmations(10)). + lp.On("LatestLogByEventSigWithConfs", mock.Anything, tp.configSetTopic, dkgAddress, evmtypes.Confirmations(10)). Return(nil, errors.New("rpc error")) c := &coordinator{ @@ -1220,7 +1221,7 @@ func TestCoordinator_ReportIsOnchain(t *testing.T) { log.BlockNumber = 195 lp.On("IndexedLogs", mock.Anything, tp.newTransmissionTopic, beaconAddress, 2, []common.Hash{ enrTopic, - }, logpoller.Confirmations(1)).Return([]logpoller.Log{log}, nil) + }, evmtypes.Confirmations(1)).Return([]logpoller.Log{log}, nil) c := &coordinator{ lp: lp, @@ -1256,7 +1257,7 @@ func TestCoordinator_ReportIsOnchain(t *testing.T) { log.BlockNumber = 195 lp.On("IndexedLogs", mock.Anything, tp.newTransmissionTopic, beaconAddress, 2, []common.Hash{ enrTopic, - }, logpoller.Confirmations(1)).Return([]logpoller.Log{log}, nil) + }, evmtypes.Confirmations(1)).Return([]logpoller.Log{log}, nil) c := &coordinator{ lp: lp, @@ -1283,7 +1284,7 @@ func TestCoordinator_ReportIsOnchain(t *testing.T) { lp := lp_mocks.NewLogPoller(t) lp.On("IndexedLogs", mock.Anything, tp.newTransmissionTopic, beaconAddress, 2, []common.Hash{ enrTopic, - }, logpoller.Confirmations(1)).Return([]logpoller.Log{}, nil) + }, evmtypes.Confirmations(1)).Return([]logpoller.Log{}, nil) c := &coordinator{ lp: lp, diff --git a/core/services/relay/evm/binding.go b/core/services/relay/evm/binding.go index 976ba05b1e8..d7a04dcc9b9 100644 --- a/core/services/relay/evm/binding.go +++ b/core/services/relay/evm/binding.go @@ -4,10 +4,12 @@ import ( "context" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" ) type readBinding interface { GetLatestValue(ctx context.Context, params, returnVal any) error + QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) Bind(ctx context.Context, binding commontypes.BoundContract) error SetCodec(codec commontypes.RemoteCodec) Register(ctx context.Context) error diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index f40da18fe27..85c837e55bc 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -38,9 +39,7 @@ type chainReader struct { commonservices.StateMachine } -func (cr *chainReader) QueryKey(_ context.Context, _ string, _ query.KeyFilter, _ query.LimitAndSort, _ any) ([]commontypes.Sequence, error) { - return nil, nil -} +var _ ChainReaderService = (*chainReader)(nil) // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. @@ -87,6 +86,15 @@ func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundCon return cr.contractBindings.Bind(ctx, bindings) } +func (cr *chainReader) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { + b, err := cr.contractBindings.GetReadBinding(contractName, filter.Key) + if err != nil { + return nil, err + } + + return b.QueryKey(ctx, filter, limitAndSort, sequenceDataType) +} + func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractReader) error { for contractName, chainContractReader := range chainContractReaders { contractAbi, err := abi.JSON(strings.NewReader(chainContractReader.ContractABI)) @@ -134,15 +142,15 @@ func (cr *chainReader) HealthReport() map[string]error { return map[string]error{cr.Name(): nil} } -func (cr *chainReader) CreateContractType(contractName, methodName string, forEncoding bool) (any, error) { - return cr.codec.CreateType(wrapItemType(contractName, methodName, forEncoding), forEncoding) +func (cr *chainReader) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { + return cr.codec.CreateType(wrapItemType(contractName, itemType, forEncoding), forEncoding) } -func wrapItemType(contractName, methodName string, isParams bool) string { +func wrapItemType(contractName, itemType string, isParams bool) string { if isParams { - return fmt.Sprintf("params.%s.%s", contractName, methodName) + return fmt.Sprintf("params.%s.%s", contractName, itemType) } - return fmt.Sprintf("return.%s.%s", contractName, methodName) + return fmt.Sprintf("return.%s.%s", contractName, itemType) } func (cr *chainReader) addMethod( @@ -181,12 +189,12 @@ func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chain return fmt.Errorf("%w: event %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) } - filterArgs, topicInfo, indexArgNames := setupEventInput(event, chainReaderDefinition) + filterArgs, codecTopicInfo, indexArgNames := setupEventInput(event, chainReaderDefinition) if err := verifyEventInputsUsed(chainReaderDefinition, indexArgNames); err != nil { return err } - if err := topicInfo.Init(); err != nil { + if err := codecTopicInfo.Init(); err != nil { return err } @@ -200,16 +208,39 @@ func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chain return err } - cr.contractBindings.AddReadBinding(contractName, eventName, &eventBinding{ - contractName: contractName, - eventName: eventName, - lp: cr.lp, - hash: event.ID, - inputInfo: inputInfo, - inputModifier: inputModifier, - topicInfo: topicInfo, - id: wrapItemType(contractName, eventName, false) + uuid.NewString(), - }) + eb := &eventBinding{ + contractName: contractName, + eventName: eventName, + lp: cr.lp, + hash: event.ID, + inputInfo: inputInfo, + inputModifier: inputModifier, + codecTopicInfo: codecTopicInfo, + topicsInfo: make(map[string]topicInfo), + eventDataWords: chainReaderDefinition.GenericDataWordNames, + id: wrapItemType(contractName, eventName, false) + uuid.NewString(), + } + + cr.contractBindings.AddReadBinding(contractName, eventName, eb) + + // set topic mappings for QueryKeys + for topicIndex, topic := range event.Inputs { + genericTopicName, ok := chainReaderDefinition.GenericTopicNames[topic.Name] + if ok { + eb.topicsInfo[genericTopicName] = topicInfo{ + Argument: topic, + topicIndex: uint64(topicIndex), + } + } + // this way querying by key/s values comparison can find its bindings + cr.contractBindings.AddReadBinding(contractName, genericTopicName, eb) + } + + // set data word mappings for QueryKeys + for genericDataWordName := range eb.eventDataWords { + // this way querying by key/s values comparison can find its bindings + cr.contractBindings.AddReadBinding(contractName, genericDataWordName, eb) + } return cr.addDecoderDef(contractName, eventName, event.Inputs, chainReaderDefinition) } @@ -239,7 +270,7 @@ func verifyEventInputsUsed(chainReaderDefinition types.ChainReaderDefinition, in return nil } -func (cr *chainReader) addEncoderDef(contractName, methodName string, args abi.Arguments, prefix []byte, chainReaderDefinition types.ChainReaderDefinition) error { +func (cr *chainReader) addEncoderDef(contractName, itemType string, args abi.Arguments, prefix []byte, chainReaderDefinition types.ChainReaderDefinition) error { // ABI.Pack prepends the method.ID to the encodings, we'll need the encoder to do the same. inputMod, err := chainReaderDefinition.InputModifications.ToModifier(evmDecoderHooks...) if err != nil { @@ -247,24 +278,74 @@ func (cr *chainReader) addEncoderDef(contractName, methodName string, args abi.A } input := types.NewCodecEntry(args, prefix, inputMod) - if err := input.Init(); err != nil { + if err = input.Init(); err != nil { return err } - cr.parsed.encoderDefs[wrapItemType(contractName, methodName, true)] = input + cr.parsed.encoderDefs[wrapItemType(contractName, itemType, true)] = input return nil } -func (cr *chainReader) addDecoderDef(contractName, methodName string, outputs abi.Arguments, def types.ChainReaderDefinition) error { +func (cr *chainReader) addDecoderDef(contractName, itemType string, outputs abi.Arguments, def types.ChainReaderDefinition) error { mod, err := def.OutputModifications.ToModifier(evmDecoderHooks...) if err != nil { return err } output := types.NewCodecEntry(outputs, nil, mod) - cr.parsed.decoderDefs[wrapItemType(contractName, methodName, false)] = output + cr.parsed.decoderDefs[wrapItemType(contractName, itemType, false)] = output return output.Init() } +// remapFilter, changes chain agnostic filters to match evm specific filters. +func (e *eventBinding) remapFilter(filter query.KeyFilter) (remappedFilter query.KeyFilter, err error) { + addEventSigFilter := false + for _, expression := range filter.Expressions { + remappedExpression, hasComparatorPrimitive, err := e.remapExpression(filter.Key, expression) + if err != nil { + return query.KeyFilter{}, err + } + remappedFilter.Expressions = append(remappedFilter.Expressions, remappedExpression) + // comparator primitive maps to event by topic or event by evm data word filters, which means that event sig filter is not needed + addEventSigFilter = addEventSigFilter != hasComparatorPrimitive + } + + if addEventSigFilter { + remappedFilter.Expressions = append(remappedFilter.Expressions, NewEventBySigFilter(e.address, e.hash)) + } + return remappedFilter, nil +} + +func (e *eventBinding) remapExpression(key string, expression query.Expression) (remappedExpression query.Expression, hasComparerPrimitive bool, err error) { + if !expression.IsPrimitive() { + for i := range expression.BoolExpression.Expressions { + remappedExpression, hasComparerPrimitive, err = e.remapExpression(key, expression.BoolExpression.Expressions[i]) + if err != nil { + return query.Expression{}, false, err + } + remappedExpression.BoolExpression.Expressions = append(remappedExpression.BoolExpression.Expressions, remappedExpression) + } + + if expression.BoolExpression.BoolOperator == query.AND { + return query.And(remappedExpression.BoolExpression.Expressions...), hasComparerPrimitive, nil + } + return query.Or(remappedExpression.BoolExpression.Expressions...), hasComparerPrimitive, nil + } + + // remap chain agnostic primitives to chain specific + switch primitive := expression.Primitive.(type) { + case *primitives.Confirmations: + remappedExpression, err = NewFinalityFilter(primitive) + return remappedExpression, hasComparerPrimitive, err + case *primitives.Comparator: + if val, ok := e.eventDataWords[primitive.Name]; ok { + return NewEventByWordFilter(e.hash, val, primitive.ValueComparators), true, nil + } + return NewEventByTopicFilter(e.hash, e.topicsInfo[key].topicIndex, primitive.ValueComparators), true, nil + default: + return expression, hasComparerPrimitive, nil + } +} + func setupEventInput(event abi.Event, def types.ChainReaderDefinition) ([]abi.Argument, types.CodecEntry, map[string]bool) { topicFieldDefs := map[string]bool{} for _, value := range def.EventInputFields { diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index f9985f2ed7f..c3cb36b93e3 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -32,7 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_example" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -46,7 +46,7 @@ const ( triggerWithAllTopics = "TriggeredWithFourTopics" ) -func TestChainReader(t *testing.T) { +func TestChainReaderGetLatestValue(t *testing.T) { t.Parallel() it := &chainReaderInterfaceTester{} RunChainReaderGetLatestValueInterfaceTests(t, it) @@ -61,7 +61,7 @@ func TestChainReader(t *testing.T) { require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) anyString := "foo" - tx, err := it.evmTest.LatestValueHolderTransactor.TriggerEventWithDynamicTopic(it.auth, anyString) + tx, err := it.evmTest.TriggerEventWithDynamicTopic(it.auth, anyString) require.NoError(t, err) it.sim.Commit() it.incNonce() @@ -110,7 +110,7 @@ func TestChainReader(t *testing.T) { } func triggerFourTopics(t *testing.T, it *chainReaderInterfaceTester, i1, i2, i3 int32) { - tx, err := it.evmTest.LatestValueHolderTransactor.TriggerWithFourTopics(it.auth, i1, i2, i3) + tx, err := it.evmTest.ChainReaderTesterTransactor.TriggerWithFourTopics(it.auth, i1, i2, i3) require.NoError(t, err) require.NoError(t, err) it.sim.Commit() @@ -126,7 +126,7 @@ type chainReaderInterfaceTester struct { auth *bind.TransactOpts sim *backends.SimulatedBackend pk *ecdsa.PrivateKey - evmTest *chain_reader_example.LatestValueHolder + evmTest *chain_reader_tester.ChainReaderTester cr evm.ChainReaderService } @@ -168,7 +168,7 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { it.chainConfig = types.ChainReaderConfig{ Contracts: map[string]types.ChainContractReader{ AnyContractName: { - ContractABI: chain_reader_example.LatestValueHolderMetaData.ABI, + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, Configs: map[string]*types.ChainReaderDefinition{ MethodTakingLatestParamsReturningTestStruct: { ChainSpecificName: "getElementAtIndex", @@ -229,7 +229,7 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { }, }, AnySecondContractName: { - ContractABI: chain_reader_example.LatestValueHolderMetaData.ABI, + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, Configs: map[string]*types.ChainReaderDefinition{ MethodReturningUint64: { ChainSpecificName: "getDifferentPrimitiveValue", @@ -278,11 +278,11 @@ func (it *chainReaderInterfaceTester) GetChainReader(t *testing.T) clcommontypes } func (it *chainReaderInterfaceTester) SetLatestValue(t *testing.T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, testStruct, (*chain_reader_example.LatestValueHolderTransactor).AddTestStruct) + it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).AddTestStruct) } func (it *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, testStruct, (*chain_reader_example.LatestValueHolderTransactor).TriggerEvent) + it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).TriggerEvent) } func (it *chainReaderInterfaceTester) GetBindings(_ *testing.T) []clcommontypes.BoundContract { @@ -292,11 +292,11 @@ func (it *chainReaderInterfaceTester) GetBindings(_ *testing.T) []clcommontypes. } } -type testStructFn = func(*chain_reader_example.LatestValueHolderTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, chain_reader_example.MidLevelTestStruct) (*evmtypes.Transaction, error) +type testStructFn = func(*chain_reader_tester.ChainReaderTesterTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, chain_reader_tester.MidLevelTestStruct) (*evmtypes.Transaction, error) func (it *chainReaderInterfaceTester) sendTxWithTestStruct(t *testing.T, testStruct *TestStruct, fn testStructFn) { tx, err := fn( - &it.evmTest.LatestValueHolderTransactor, + &it.evmTest.ChainReaderTesterTransactor, it.auth, *testStruct.Field, testStruct.DifferentField, @@ -356,7 +356,7 @@ func (it *chainReaderInterfaceTester) deployNewContract(t *testing.T) string { // Not sure if there's a better way to get it. it.auth.GasLimit = 10552800 - address, tx, ts, err := chain_reader_example.DeployLatestValueHolder(it.auth, it.sim) + address, tx, ts, err := chain_reader_tester.DeployChainReaderTester(it.auth, it.sim) require.NoError(t, err) it.sim.Commit() @@ -412,8 +412,8 @@ func getOracleIDs(first TestStruct) [32]byte { return oracleIDs } -func toInternalType(testStruct TestStruct) chain_reader_example.TestStruct { - return chain_reader_example.TestStruct{ +func toInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { + return chain_reader_tester.TestStruct{ Field: *testStruct.Field, DifferentField: testStruct.DifferentField, OracleId: byte(testStruct.OracleID), @@ -425,10 +425,10 @@ func toInternalType(testStruct TestStruct) chain_reader_example.TestStruct { } } -func midToInternalType(m MidLevelTestStruct) chain_reader_example.MidLevelTestStruct { - return chain_reader_example.MidLevelTestStruct{ +func midToInternalType(m MidLevelTestStruct) chain_reader_tester.MidLevelTestStruct { + return chain_reader_tester.MidLevelTestStruct{ FixedBytes: m.FixedBytes, - Inner: chain_reader_example.InnerTestStruct{ + Inner: chain_reader_tester.InnerTestStruct{ IntVal: int64(m.Inner.I), S: m.Inner.S, }, diff --git a/core/services/relay/evm/codec_test.go b/core/services/relay/evm/codec_test.go index 2f9a4639d41..0597560aaec 100644 --- a/core/services/relay/evm/codec_test.go +++ b/core/services/relay/evm/codec_test.go @@ -16,7 +16,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_example" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -148,11 +148,11 @@ func encodeFieldsOnSliceOrArray(t *testing.T, request *EncodeRequest) []byte { switch request.TestOn { case TestItemArray1Type: - args[0] = [1]chain_reader_example.TestStruct{toInternalType(request.TestStructs[0])} + args[0] = [1]chain_reader_tester.TestStruct{toInternalType(request.TestStructs[0])} case TestItemArray2Type: - args[0] = [2]chain_reader_example.TestStruct{toInternalType(request.TestStructs[0]), toInternalType(request.TestStructs[1])} + args[0] = [2]chain_reader_tester.TestStruct{toInternalType(request.TestStructs[0]), toInternalType(request.TestStructs[1])} default: - tmp := make([]chain_reader_example.TestStruct, len(request.TestStructs)) + tmp := make([]chain_reader_tester.TestStruct, len(request.TestStructs)) for i, ts := range request.TestStructs { tmp[i] = toInternalType(ts) } diff --git a/core/services/relay/evm/dsl.go b/core/services/relay/evm/dsl.go new file mode 100644 index 00000000000..05592feb996 --- /dev/null +++ b/core/services/relay/evm/dsl.go @@ -0,0 +1,96 @@ +package evm + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type EventBySigFilter struct { + Address common.Address + EventSig common.Hash +} + +func NewEventBySigFilter(address common.Address, eventSig common.Hash) query.Expression { + var searchEventFilter *EventBySigFilter + searchEventFilter.Address = address + searchEventFilter.EventSig = eventSig + return query.Expression{Primitive: searchEventFilter} +} + +func (f *EventBySigFilter) Accept(visitor primitives.Visitor) { + switch v := visitor.(type) { + case *PgDSLParser: + v.VisitEventBySigFilter(f) + } +} + +type EventByTopicFilter struct { + EventSig common.Hash + Topic uint64 + ValueComparators []primitives.ValueComparator +} + +func NewEventByTopicFilter(eventSig common.Hash, topicIndex uint64, valueComparators []primitives.ValueComparator) query.Expression { + var eventByIndexFilter *EventByTopicFilter + eventByIndexFilter.EventSig = eventSig + eventByIndexFilter.Topic = topicIndex + eventByIndexFilter.ValueComparators = valueComparators + + return query.Expression{Primitive: eventByIndexFilter} +} + +func (f *EventByTopicFilter) Accept(visitor primitives.Visitor) { + switch v := visitor.(type) { + case *PgDSLParser: + v.VisitEventTopicsByValueFilter(f) + } +} + +type EventByWordFilter struct { + EventSig common.Hash + WordIndex uint8 + ValueComparators []primitives.ValueComparator +} + +func NewEventByWordFilter(eventSig common.Hash, wordIndex uint8, valueComparators []primitives.ValueComparator) query.Expression { + var eventByIndexFilter *EventByWordFilter + eventByIndexFilter.EventSig = eventSig + eventByIndexFilter.WordIndex = wordIndex + eventByIndexFilter.ValueComparators = valueComparators + return query.Expression{Primitive: eventByIndexFilter} +} + +func (f *EventByWordFilter) Accept(visitor primitives.Visitor) { + switch v := visitor.(type) { + case *PgDSLParser: + v.VisitEventByWordFilter(f) + } +} + +type FinalityFilter struct { + Confs evmtypes.Confirmations +} + +func NewFinalityFilter(filter *primitives.Confirmations) (query.Expression, error) { + // TODO chain agnostic confidence levels that map to evm finality + switch filter.ConfirmationLevel { + case primitives.Finalized: + return query.Expression{Primitive: &FinalityFilter{evmtypes.Finalized}}, nil + case primitives.Unconfirmed: + return query.Expression{Primitive: &FinalityFilter{evmtypes.Unconfirmed}}, nil + default: + return query.Expression{}, fmt.Errorf("invalid finality confirmations filter value %v", filter.ConfirmationLevel) + } +} + +func (f *FinalityFilter) Accept(visitor primitives.Visitor) { + switch v := visitor.(type) { + case *PgDSLParser: + v.VisitFinalityFilter(f) + } +} diff --git a/core/services/relay/evm/event_binding.go b/core/services/relay/evm/event_binding.go index bded6ba476d..f43576de4ff 100644 --- a/core/services/relay/evm/event_binding.go +++ b/core/services/relay/evm/event_binding.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -31,14 +32,49 @@ type eventBinding struct { lock sync.Mutex inputInfo types.CodecEntry inputModifier codec.Modifier - topicInfo types.CodecEntry + codecTopicInfo types.CodecEntry + // key is generic topic name + topicsInfo map[string]topicInfo + // key is a predefined generic name for evm log event data word + // for eg. first evm data word(32bytes) of USDC log event is value so the key can be called value + eventDataWords map[string]uint8 // used to allow Register and Unregister to be unique in case two bindings have the same event. // otherwise, if one unregisters, it'll unregister both with the LogPoller. id string } +type topicInfo struct { + abi.Argument + topicIndex uint64 +} + var _ readBinding = &eventBinding{} +func (e *eventBinding) decodeLogsIntoSequences(ctx context.Context, logs []logpoller.Log, into any) ([]commontypes.Sequence, error) { + var sequences []commontypes.Sequence + for i := range logs { + sequence := commontypes.Sequence{ + // TODO SequenceCursor, should be combination of block, eventsig, topic and also match a proper db cursor?... + Cursor: "TODO", + Head: commontypes.Head{ + Identifier: fmt.Sprint(logs[i].BlockNumber), + Hash: logs[i].BlockHash.Bytes(), + Timestamp: uint64(logs[i].BlockTimestamp.Unix()), + }, + // TODO test this + Data: reflect.New(reflect.TypeOf(into).Elem()), + } + + if err := e.decodeLog(ctx, &logs[i], sequence.Data); err != nil { + return nil, err + } + + sequences = append(sequences, sequence) + } + + return sequences, nil +} + func (e *eventBinding) SetCodec(codec commontypes.RemoteCodec) { e.codec = codec } @@ -81,9 +117,9 @@ func (e *eventBinding) GetLatestValue(ctx context.Context, params, into any) err return fmt.Errorf("%w: event not bound", commontypes.ErrInvalidType) } - confs := logpoller.Finalized + confs := evmtypes.Finalized if e.pending { - confs = logpoller.Unconfirmed + confs = evmtypes.Unconfirmed } if len(e.inputInfo.Args()) == 0 { @@ -93,6 +129,20 @@ func (e *eventBinding) GetLatestValue(ctx context.Context, params, into any) err return e.getLatestValueWithFilters(ctx, confs, params, into) } +func (e *eventBinding) QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { + remappedFilter, err := e.remapFilter(filter) + if err != nil { + return nil, err + } + + logs, err := e.lp.FilteredLogs(remappedFilter, limitAndSort) + if err != nil { + return nil, err + } + + return e.decodeLogsIntoSequences(ctx, logs, sequenceDataType) +} + func (e *eventBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { if err := e.Unregister(ctx); err != nil { return err @@ -108,7 +158,7 @@ func (e *eventBinding) Bind(ctx context.Context, binding commontypes.BoundContra return nil } -func (e *eventBinding) getLatestValueWithoutFilters(ctx context.Context, confs logpoller.Confirmations, into any) error { +func (e *eventBinding) getLatestValueWithoutFilters(ctx context.Context, confs evmtypes.Confirmations, into any) error { log, err := e.lp.LatestLogByEventSigWithConfs(ctx, e.hash, e.address, confs) if err = wrapInternalErr(err); err != nil { return err @@ -118,7 +168,7 @@ func (e *eventBinding) getLatestValueWithoutFilters(ctx context.Context, confs l } func (e *eventBinding) getLatestValueWithFilters( - ctx context.Context, confs logpoller.Confirmations, params, into any) error { + ctx context.Context, confs evmtypes.Confirmations, params, into any) error { offChain, err := e.convertToOffChainType(params) if err != nil { return err @@ -167,8 +217,7 @@ func (e *eventBinding) getLatestValueWithFilters( } func (e *eventBinding) convertToOffChainType(params any) (any, error) { - itemType := wrapItemType(e.contractName, e.eventName, true) - offChain, err := e.codec.CreateType(itemType, true) + offChain, err := e.codec.CreateType(wrapItemType(e.contractName, e.eventName, true), true) if err != nil { return nil, err } @@ -256,12 +305,11 @@ func (e *eventBinding) derefTopics(topics []any) error { } func (e *eventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into any) error { - dataType := wrapItemType(e.contractName, e.eventName, false) - if err := e.codec.Decode(ctx, log.Data, into, dataType); err != nil { + if err := e.codec.Decode(ctx, log.Data, into, wrapItemType(e.contractName, e.eventName, false)); err != nil { return err } - topics := make([]common.Hash, len(e.topicInfo.Args())) + topics := make([]common.Hash, len(e.codecTopicInfo.Args())) if len(log.Topics) < len(topics)+1 { return fmt.Errorf("%w: not enough topics to decode", commontypes.ErrInvalidType) } @@ -271,7 +319,7 @@ func (e *eventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into a } topicsInto := map[string]any{} - if err := abi.ParseTopicsIntoMap(topicsInto, e.topicInfo.Args(), topics); err != nil { + if err := abi.ParseTopicsIntoMap(topicsInto, e.codecTopicInfo.Args(), topics); err != nil { return fmt.Errorf("%w: %w", commontypes.ErrInvalidType, err) } diff --git a/core/services/relay/evm/method_binding.go b/core/services/relay/evm/method_binding.go index 154c5b16a18..7484d17c3ef 100644 --- a/core/services/relay/evm/method_binding.go +++ b/core/services/relay/evm/method_binding.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) @@ -27,11 +28,15 @@ func (m *methodBinding) SetCodec(codec commontypes.RemoteCodec) { m.codec = codec } -func (m *methodBinding) Register(ctx context.Context) error { +func (m *methodBinding) Register(_ context.Context) error { return nil } -func (m *methodBinding) Unregister(ctx context.Context) error { +func (m *methodBinding) Unregister(_ context.Context) error { + return nil +} + +func (m *methodBinding) UnregisterAll(_ context.Context) error { return nil } @@ -59,7 +64,11 @@ func (m *methodBinding) GetLatestValue(ctx context.Context, params, returnValue return m.codec.Decode(ctx, bytes, returnValue, wrapItemType(m.contractName, m.method, false)) } -func (m *methodBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { +func (m *methodBinding) QueryKey(_ context.Context, _ query.KeyFilter, _ query.LimitAndSort, _ any) ([]commontypes.Sequence, error) { + return nil, nil +} + +func (m *methodBinding) Bind(_ context.Context, binding commontypes.BoundContract) error { m.address = common.HexToAddress(binding.Address) m.bound = true return nil diff --git a/core/services/relay/evm/pgparser.go b/core/services/relay/evm/pgparser.go new file mode 100644 index 00000000000..62e95c10121 --- /dev/null +++ b/core/services/relay/evm/pgparser.go @@ -0,0 +1,36 @@ +package evm + +import ( + "math/big" + + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" +) + +// PgDSLParser is a visitor that builds a postgres query and arguments from a query.KeyFilter +type PgDSLParser struct { + //TODO implement psql parser +} + +var _ primitives.Visitor = (*PgDSLParser)(nil) + +func NewPgParser(evmChainID *big.Int) *PgDSLParser { + return &PgDSLParser{} +} + +func (v *PgDSLParser) Comparator(_ primitives.Comparator) {} + +func (v *PgDSLParser) Block(_ primitives.Block) {} + +func (v *PgDSLParser) Confirmations(_ primitives.Confirmations) {} + +func (v *PgDSLParser) Timestamp(_ primitives.Timestamp) {} + +func (v *PgDSLParser) TxHash(_ primitives.TxHash) {} + +func (v *PgDSLParser) VisitEventTopicsByValueFilter(_ *EventByTopicFilter) {} + +func (v *PgDSLParser) VisitEventByWordFilter(_ *EventByWordFilter) {} + +func (v *PgDSLParser) VisitEventBySigFilter(_ *EventBySigFilter) {} + +func (v *PgDSLParser) VisitFinalityFilter(_ *FinalityFilter) {} diff --git a/core/services/relay/evm/types/types.go b/core/services/relay/evm/types/types.go index 26e1c6f7128..650a75d6006 100644 --- a/core/services/relay/evm/types/types.go +++ b/core/services/relay/evm/types/types.go @@ -56,6 +56,12 @@ type chainReaderDefinitionFields struct { // EventInputFields allows you to choose which indexed fields are expected from the input EventInputFields []string `json:"eventInputFields,omitempty"` + // GenericTopicNames helps QueryingKeys not rely on EVM specific topic names. Key is chain specific name, value is generic name. + // This helps us translate chain agnostic querying key "transfer-value" to EVM specific "evmTransferEvent-weiAmountTopic". + GenericTopicNames map[string]string `json:"genericTopicNames,omitempty"` + // key is a predefined generic name for evm log event data word + // for eg. first evm data word(32bytes) of USDC log event is value so the key can be called value + GenericDataWordNames map[string]uint8 `json:"genericDataWordNames,omitempty"` } func (d *ChainReaderDefinition) MarshalText() ([]byte, error) { diff --git a/core/services/vrf/v2/listener_v2_log_listener.go b/core/services/vrf/v2/listener_v2_log_listener.go index 2d2c08b8590..6f756dd02f0 100644 --- a/core/services/vrf/v2/listener_v2_log_listener.go +++ b/core/services/vrf/v2/listener_v2_log_listener.go @@ -148,8 +148,8 @@ func (lsn *listenerV2) initializeLastProcessedBlock(ctx context.Context) (lastPr lsn.coordinator.Address(), // address 1, // topic index []common.Hash{lsn.job.VRFSpec.PublicKey.MustHash()}, // topic values - fromTimestamp, // from time - logpoller.Finalized, // confs + fromTimestamp, // from time + evmtypes.Finalized, // confs ) if err != nil { return 0, fmt.Errorf("LogPoller.LogsCreatedAfter RandomWordsRequested logs: %w", err) @@ -162,7 +162,7 @@ func (lsn *listenerV2) initializeLastProcessedBlock(ctx context.Context) (lastPr lsn.coordinator.RandomWordsFulfilledTopic(), // event sig lsn.coordinator.Address(), // address fromTimestamp, // from time - logpoller.Finalized, // confs + evmtypes.Finalized, // confs ) if err != nil { return 0, fmt.Errorf("LogPoller.LogsCreatedAfter RandomWordsFulfilled logs: %w", err) From c0d807507ecbd1b7aeae8a3f6076c2ec5bd7ebb6 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 8 May 2024 08:16:19 -0500 Subject: [PATCH 35/35] core/services: fix ocrWrapper saveError contexts --- .changeset/big-trees-help.md | 5 ++ core/services/ocr/delegate.go | 4 +- core/services/ocr2/delegate.go | 90 +++++++++++++++++--------- core/services/ocrbootstrap/delegate.go | 18 +++--- core/services/ocrcommon/ocr_logger.go | 30 +++++++++ 5 files changed, 104 insertions(+), 43 deletions(-) create mode 100644 .changeset/big-trees-help.md create mode 100644 core/services/ocrcommon/ocr_logger.go diff --git a/.changeset/big-trees-help.md b/.changeset/big-trees-help.md new file mode 100644 index 00000000000..f826d257afa --- /dev/null +++ b/.changeset/big-trees-help.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +core/services: fix ocrWrapper saveError contexts #internal diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go index 690e9ad7c71..e748823ad71 100644 --- a/core/services/ocr/delegate.go +++ b/core/services/ocr/delegate.go @@ -14,7 +14,6 @@ import ( ocr "github.com/smartcontractkit/libocr/offchainreporting" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" - commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" @@ -155,9 +154,10 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] v2Bootstrappers = peerWrapper.P2PConfig().V2().DefaultBootstrappers() } - ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR().TraceLogging(), func(msg string) { + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR().TraceLogging(), func(ctx context.Context, msg string) { d.jobORM.TryRecordError(ctx, jb.ID, msg) }) + services = append(services, ocrLogger) lc := toLocalConfig(chain.Config().EVM(), chain.Config().EVM().OCR(), d.cfg.Insecure(), *concreteSpec, d.cfg.OCR()) if err = ocr.SanityCheckLocalConfig(lc); err != nil { diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 1addae25601..e8db1cfe2b3 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -25,7 +25,6 @@ import ( ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner" ocr2keepers21config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" - commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" @@ -397,10 +396,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi return nil, errors.New("peerWrapper is not started. OCR2 jobs require a started and running p2p v2 peer") } - ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") - }) - lc, err := validate.ToLocalConfig(d.cfg.OCR2(), d.cfg.Insecure(), *spec) if err != nil { return nil, err @@ -438,22 +433,22 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi ctx = lggrCtx.ContextWithValues(ctx) switch spec.PluginType { case types.Mercury: - return d.newServicesMercury(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) + return d.newServicesMercury(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.LLO: - return d.newServicesLLO(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) + return d.newServicesLLO(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.Median: - return d.newServicesMedian(ctx, lggr, jb, bootstrapPeers, kb, kvStore, ocrDB, lc, ocrLogger) + return d.newServicesMedian(ctx, lggr, jb, bootstrapPeers, kb, kvStore, ocrDB, lc) case types.DKG: - return d.newServicesDKG(lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) + return d.newServicesDKG(lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.OCR2VRF: return d.newServicesOCR2VRF(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.OCR2Keeper: - return d.newServicesOCR2Keepers(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger) + return d.newServicesOCR2Keepers(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc) case types.Functions: const ( @@ -463,10 +458,10 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi ) thresholdPluginDB := NewDB(d.ds, spec.ID, thresholdPluginId, lggr) s4PluginDB := NewDB(d.ds, spec.ID, s4PluginId, lggr) - return d.newServicesOCR2Functions(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, thresholdPluginDB, s4PluginDB, lc, ocrLogger) + return d.newServicesOCR2Functions(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, thresholdPluginDB, s4PluginDB, lc) case types.GenericPlugin: - return d.newServicesGenericPlugin(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, d.capabilitiesRegistry, + return d.newServicesGenericPlugin(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, d.capabilitiesRegistry, kvStore) default: @@ -525,7 +520,6 @@ func (d *Delegate) newServicesGenericPlugin( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, capabilitiesRegistry core.CapabilitiesRegistry, keyValueStore core.KeyValueStore, ) (srvs []job.ServiceCtx, err error) { @@ -655,6 +649,11 @@ func (d *Delegate) newServicesGenericPlugin( synchronization.TelemetryType(pCfg.TelemetryType), ) + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + srvs = append(srvs, ocrLogger) + switch pCfg.OCRVersion { case 2: plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerClientConn, pr, ta, @@ -723,7 +722,6 @@ func (d *Delegate) newServicesMercury( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { if jb.OCR2OracleSpec.FeedID == nil || (*jb.OCR2OracleSpec.FeedID == (common.Hash{})) { return nil, errors.Errorf("ServicesForSpec: mercury job type requires feedID") @@ -775,6 +773,10 @@ func (d *Delegate) newServicesMercury( // https://smartcontract-it.atlassian.net/browse/MERC-3386 lc.ContractConfigTrackerPollInterval = 1 * time.Second // Mercury requires a fast poll interval, this is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520 + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + oracleArgsNoPlugin := libocr2.MercuryOracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -803,6 +805,8 @@ func (d *Delegate) newServicesMercury( lggr.Infow("Enhanced telemetry is disabled for mercury job", "job", jb.Name) } + mercuryServices = append(mercuryServices, ocrLogger) + return mercuryServices, err2 } @@ -814,7 +818,6 @@ func (d *Delegate) newServicesLLO( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { lggr = logger.Sugared(lggr.Named("LLO")) spec := jb.OCR2OracleSpec @@ -906,6 +909,10 @@ func (d *Delegate) newServicesLLO( lggr.Infof("Using on-chain signing keys for LLO job %d (%s): %v", jb.ID, jb.Name.ValueOrZero(), kbm) kr := llo.NewOnchainKeyring(lggr, kbm) + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + cfg := llo.DelegateConfig{ Logger: lggr, DataSource: d.ds, @@ -934,7 +941,7 @@ func (d *Delegate) newServicesLLO( if err != nil { return nil, err } - return []job.ServiceCtx{provider, oracle}, nil + return []job.ServiceCtx{provider, ocrLogger, oracle}, nil } func (d *Delegate) newServicesMedian( @@ -946,7 +953,6 @@ func (d *Delegate) newServicesMedian( kvStore job.KVStore, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec @@ -955,6 +961,10 @@ func (d *Delegate) newServicesMedian( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "median"} } + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + oracleArgsNoPlugin := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -988,6 +998,8 @@ func (d *Delegate) newServicesMedian( lggr.Infow("Enhanced telemetry is disabled for job", "job", jb.Name) } + medianServices = append(medianServices, ocrLogger) + return medianServices, err2 } @@ -998,7 +1010,6 @@ func (d *Delegate) newServicesDKG( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec rid, err := spec.RelayID() @@ -1028,6 +1039,9 @@ func (d *Delegate) newServicesDKG( if err2 != nil { return nil, err2 } + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) noopMonitoringEndpoint := telemetry.NoopAgent{} oracleArgsNoPlugin := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, @@ -1044,7 +1058,12 @@ func (d *Delegate) newServicesDKG( OnchainKeyring: kb, MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return dkg.NewDKGServices(jb, dkgProvider, lggr, ocrLogger, d.dkgSignKs, d.dkgEncryptKs, chain.Client(), oracleArgsNoPlugin, d.ds, chain.ID(), spec.Relay) + services, err := dkg.NewDKGServices(jb, dkgProvider, lggr, ocrLogger, d.dkgSignKs, d.dkgEncryptKs, chain.Client(), oracleArgsNoPlugin, d.ds, chain.ID(), spec.Relay) + if err != nil { + return nil, err + } + services = append(services, ocrLogger) + return services, nil } func (d *Delegate) newServicesOCR2VRF( @@ -1167,12 +1186,10 @@ func (d *Delegate) newServicesOCR2VRF( "jobName", jb.Name.ValueOrZero(), "jobID", jb.ID, ) - vrfLogger := commonlogger.NewOCRWrapper(l.With( - "vrfContractID", spec.ContractID), d.cfg.OCR2().TraceLogging(), func(msg string) { + vrfLogger := ocrcommon.NewOCRWrapper(l.With("vrfContractID", spec.ContractID), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) - dkgLogger := commonlogger.NewOCRWrapper(l.With( - "dkgContractID", cfg.DKGContractAddress), d.cfg.OCR2().TraceLogging(), func(msg string) { + dkgLogger := ocrcommon.NewOCRWrapper(l.With("dkgContractID", cfg.DKGContractAddress), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { @@ -1233,7 +1250,6 @@ func (d *Delegate) newServicesOCR2Keepers( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec var cfg ocr2keeper.PluginConfig @@ -1247,14 +1263,14 @@ func (d *Delegate) newServicesOCR2Keepers( switch cfg.ContractVersion { case "v2.1": - return d.newServicesOCR2Keepers21(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) + return d.newServicesOCR2Keepers21(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, cfg, spec) case "v2.1+": // Future contracts of v2.1 (v2.x) will use the same job spec as v2.1 - return d.newServicesOCR2Keepers21(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) + return d.newServicesOCR2Keepers21(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, cfg, spec) case "v2.0": - return d.newServicesOCR2Keepers20(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) + return d.newServicesOCR2Keepers20(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, cfg, spec) default: - return d.newServicesOCR2Keepers20(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, ocrLogger, cfg, spec) + return d.newServicesOCR2Keepers20(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc, cfg, spec) } } @@ -1266,7 +1282,6 @@ func (d *Delegate) newServicesOCR2Keepers21( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, cfg ocr2keeper.PluginConfig, spec *job.OCR2OracleSpec, ) ([]job.ServiceCtx, error) { @@ -1348,6 +1363,9 @@ func (d *Delegate) newServicesOCR2Keepers21( if cfg.ServiceQueueLength != 0 { conf.ServiceQueueLength = cfg.ServiceQueueLength } + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) dConf := ocr2keepers21.DelegateConfig{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, @@ -1394,6 +1412,7 @@ func (d *Delegate) newServicesOCR2Keepers21( keeperProvider.UpkeepStateStore(), keeperProvider.TransmitEventProvider(), pluginService, + ocrLogger, } if cfg.CaptureAutomationCustomTelemetry != nil && *cfg.CaptureAutomationCustomTelemetry || @@ -1422,7 +1441,6 @@ func (d *Delegate) newServicesOCR2Keepers20( kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, cfg ocr2keeper.PluginConfig, spec *job.OCR2OracleSpec, ) ([]job.ServiceCtx, error) { @@ -1498,6 +1516,10 @@ func (d *Delegate) newServicesOCR2Keepers20( CacheClean: conf.CacheEvictionInterval, } + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + dConf := ocr2keepers20.DelegateConfig{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -1532,6 +1554,7 @@ func (d *Delegate) newServicesOCR2Keepers20( keeperProvider, rgstry, logProvider, + ocrLogger, pluginService, }, nil } @@ -1546,7 +1569,6 @@ func (d *Delegate) newServicesOCR2Functions( thresholdOcrDB *db, s4OcrDB *db, lc ocrtypes.LocalConfig, - ocrLogger commontypes.Logger, ) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec @@ -1597,6 +1619,10 @@ func (d *Delegate) newServicesOCR2Functions( return nil, err } + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) + functionsOracleArgs := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -1682,7 +1708,7 @@ func (d *Delegate) newServicesOCR2Functions( return nil, errors.Wrap(err, "error calling NewFunctionsServices") } - return append([]job.ServiceCtx{functionsProvider, thresholdProvider, s4Provider}, functionsServices...), nil + return append([]job.ServiceCtx{functionsProvider, thresholdProvider, s4Provider, ocrLogger}, functionsServices...), nil } // errorLog implements [loop.ErrorLog] diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go index 4f927faa009..fdcb68ceecc 100644 --- a/core/services/ocrbootstrap/delegate.go +++ b/core/services/ocrbootstrap/delegate.go @@ -9,7 +9,6 @@ import ( ocr "github.com/smartcontractkit/libocr/offchainreporting2plus" - commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -163,14 +162,15 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] "ContractTransmitterTransmitTimeout", lc.ContractTransmitterTransmitTimeout, "DatabaseTimeout", lc.DatabaseTimeout, ) + ocrLogger := ocrcommon.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(ctx context.Context, msg string) { + logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") + }) bootstrapNodeArgs := ocr.BootstrapperArgs{ - BootstrapperFactory: d.peerWrapper.Peer2, - ContractConfigTracker: configProvider.ContractConfigTracker(), - Database: NewDB(d.ds, spec.ID, lggr), - LocalConfig: lc, - Logger: commonlogger.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(msg string) { - logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") - }), + BootstrapperFactory: d.peerWrapper.Peer2, + ContractConfigTracker: configProvider.ContractConfigTracker(), + Database: NewDB(d.ds, spec.ID, lggr), + LocalConfig: lc, + Logger: ocrLogger, OffchainConfigDigester: configProvider.OffchainConfigDigester(), } lggr.Debugw("Launching new bootstrap node", "args", bootstrapNodeArgs) @@ -178,7 +178,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] if err != nil { return nil, errors.Wrap(err, "error calling NewBootstrapNode") } - return []job.ServiceCtx{configProvider, job.NewServiceAdapter(bootstrapper)}, nil + return []job.ServiceCtx{configProvider, ocrLogger, job.NewServiceAdapter(bootstrapper)}, nil } // AfterJobCreated satisfies the job.Delegate interface. diff --git a/core/services/ocrcommon/ocr_logger.go b/core/services/ocrcommon/ocr_logger.go new file mode 100644 index 00000000000..50a8c9adc71 --- /dev/null +++ b/core/services/ocrcommon/ocr_logger.go @@ -0,0 +1,30 @@ +package ocrcommon + +import ( + "context" + + ocrtypes "github.com/smartcontractkit/libocr/commontypes" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" +) + +type ocrLoggerService struct { + stopCh services.StopChan + ocrtypes.Logger +} + +func NewOCRWrapper(l logger.Logger, trace bool, saveError func(context.Context, string)) *ocrLoggerService { + stopCh := make(services.StopChan) + return &ocrLoggerService{ + stopCh: stopCh, + Logger: logger.NewOCRWrapper(l, trace, func(s string) { + ctx, cancel := stopCh.NewCtx() + defer cancel() + saveError(ctx, s) + }), + } +} + +func (*ocrLoggerService) Start(context.Context) error { return nil } +func (s *ocrLoggerService) Close() error { close(s.stopCh); return nil }